/*
 * Zettelkasten - nach Luhmann
 * Copyright (C) 2001-2015 by Daniel Lüdecke (http://www.danielluedecke.de)
 * 
 * Homepage: http://zettelkasten.danielluedecke.de
 * 
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation; either version 3 of 
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this program;
 * if not, see <http://www.gnu.org/licenses/>.
 * 
 * 
 * Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU
 * General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben
 * und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (wenn Sie möchten)
 * jeder späteren Version.
 * 
 * Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein 
 * wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder 
 * der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der 
 * GNU General Public License.
 * 
 * Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm 
 * erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>.
 */
package de.danielluedecke.zettelkasten;

import com.explodingpixels.macwidgets.BottomBar;
import com.explodingpixels.macwidgets.BottomBarSize;
import de.danielluedecke.zettelkasten.util.Tools;
import de.danielluedecke.zettelkasten.util.Constants;
import de.danielluedecke.zettelkasten.util.HtmlUbbUtil;
import de.danielluedecke.zettelkasten.util.classes.EntryStringTransferHandler;
import com.explodingpixels.macwidgets.MacUtils;
import com.explodingpixels.macwidgets.MacWidgetFactory;
import com.explodingpixels.macwidgets.UnifiedToolBar;
import com.explodingpixels.widgets.WindowUtils;

import de.danielluedecke.zettelkasten.database.AutoKorrektur;
import de.danielluedecke.zettelkasten.database.DesktopData;
import de.danielluedecke.zettelkasten.util.classes.TasksStatusBar;
import de.danielluedecke.zettelkasten.database.StenoData;
import de.danielluedecke.zettelkasten.mac.MacSourceDesktopTree;
import de.danielluedecke.zettelkasten.database.BibTeX;
import de.danielluedecke.zettelkasten.database.Bookmarks;
import de.danielluedecke.zettelkasten.database.Daten;
import de.danielluedecke.zettelkasten.database.TasksData;
import de.danielluedecke.zettelkasten.mac.MacToolbarButton;
import de.danielluedecke.zettelkasten.mac.ZknMacWidgetFactory;
import de.danielluedecke.zettelkasten.settings.AcceleratorKeys;
import de.danielluedecke.zettelkasten.settings.Settings;
import de.danielluedecke.zettelkasten.tasks.TaskProgressDialog;
import de.danielluedecke.zettelkasten.tasks.export.ExportTools;
import de.danielluedecke.zettelkasten.util.ColorUtil;
import de.danielluedecke.zettelkasten.util.FileOperationsUtil;
import de.danielluedecke.zettelkasten.util.PlatformUtil;
import de.danielluedecke.zettelkasten.util.TreeUtil;
import de.danielluedecke.zettelkasten.util.classes.TreeUserObject;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.GraphicsDevice;
import java.awt.IllegalComponentStateException;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.print.PrinterException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.swing.*;
import javax.swing.border.MatteBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.text.AttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.jdesktop.application.Action;
import org.jdesktop.application.Application;
import org.jdesktop.application.ApplicationContext;
import org.jdesktop.application.Task;
import org.jdesktop.application.TaskMonitor;
import org.jdesktop.application.TaskService;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;

/**
 *
 * @author danielludecke
 */
public class DesktopFrame extends javax.swing.JFrame implements WindowListener {

	/**
	 * Reference to the main data class.
	 */
	private final Daten dataObj;
	/**
	 *
	 */
	private final TasksData taskdata;
	/**
	 * Reference to the desktop data class.
	 */
	private final DesktopData desktopObj;
	/**
	 * Reference to the bookmarks data class.
	 */
	private final Bookmarks bookmarksObj;
	/**
	 * Reference to the settings class.
	 */
	private final Settings settingsObj;
	/**
	 *
	 */
	private final BibTeX bibtexObj;
	/**
	 *
	 */
	private final AutoKorrektur spellObj;
	/**
	 *
	 */
	private final StenoData stenoObj;
	/**
	 * CAccelerator object, which contains the XML data of the accelerator table for
	 * the menus
	 */
	private final AcceleratorKeys accKeys;
	/**
	 *
	 */
	private createDisplayTask cDisplayTask = null;
	/**
	 * This variable indicates whether the task that updates the display is already
	 * running or not...
	 */
	private boolean cDisplayTaskIsRunning = false;
	/**
	 * Indicates whether the main entries' headings are visible or not.
	 */
	private boolean isHeadingVisible = true;
	private boolean isLuhmannIconVisible;
	/**
	 *
	 */
	private boolean isEntryNumberVisible = true;
	/**
	 *
	 */
	private boolean isEditModeActive = false;
	private boolean isSidebarHidden = true;
	/**
	 * Indicates the number of that entry that should be immediately selected after
	 * the treeview is updated
	 */
	private int displayentrynr = -1;
	/**
	 * Flag that indicates whether the message box warning when adding multiple
	 * entries should only pop up once and not for each multiple entry
	 */
	private boolean showMultipleEntryMsg;
	/**
	 *
	 */
	private String editModeTimeStamp = "";
	/**
	 * Used for the {@link #addLuhmann addLuhmann} Action.
	 */
	private StringBuilder luhmannnumbers;
	/**
	 * This value stores entries that can be inserted using the {@link #pasteNode()
	 * pasteNode()}.
	 */
	public int[] clipEntries;
	/**
	 * This variable indicates whether the entry in the clipboard is a bullet (true)
	 * or a child-entry (false)
	 */
	private boolean clipBullet = false;
	/**
	 * This variable stores the name of the bullet that was copied or cut to the
	 * clipboard. we need this information when inserting the bullet, so we can
	 * avoid double bullet-entries (double names).
	 */
	private String clipBulletName;
	/**
	 * This variable stores modifications from entries that are cut or copied within
	 * the jTree. Since cutting out an entry will delete it, the timestamp reference
	 * to possible modifications is lost. To avoid this, we store the modifications
	 * in this variable.
	 */
	private String clipModifiedEntryContent = null;
	/**
	 * This variable stores the treepath when a node was dragged&dropped within the
	 * jtreedesktop
	 */
	private DefaultMutableTreeNode movedNodeToRemove = null;
	/**
	 *
	 */
	private final String lineseparator;
	/**
	 *
	 */
	private String multipleOccurencesMessage;
	/**
	 * Reference to the main frame.
	 */
	private final ZettelkastenView zknframe;
	/**
	 *
	 */
	private int findlivepos;
	/**
	 *
	 */
	private int findlivemax = 1;
	/**
	 * create a new stringbuilder that will contain the plain text of entries in the
	 * editorpane, so we can count the words
	 */
	private final StringBuilder sbWordCountDisplayTask = new StringBuilder();
	/**
	 *
	 */
	private String completePage = "";
	/**
	 * This variable gets the graphic device and ist needed for
	 * full-screen-functionality. see {@link #viewFullScreen() viewFullScreen()} for
	 * more details.
	 */
	private final GraphicsDevice graphicdevice = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
			.getDefaultScreenDevice();
	/**
	 *
	 */
	private final JFrame mainframe;
	/**
	 * get the strings for file descriptions from the resource map
	 */
	private final org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application
			.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext()
			.getResourceMap(DesktopFrame.class);
	/**
	 * get the strings for file descriptions from the resource map
	 */
	private final org.jdesktop.application.ResourceMap toolbarResourceMap = org.jdesktop.application.Application
			.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext()
			.getResourceMap(ToolbarIcons.class);

	/**
	 *
	 * @param zkn
	 * @param td
	 * @param d
	 * @param bm
	 * @param dk
	 * @param s
	 * @param ak
	 * @param bt
	 * @param st
	 * @param auk
	 */
	public DesktopFrame(ZettelkastenView zkn, TasksData td, Daten d, Bookmarks bm, DesktopData dk, Settings s,
			AcceleratorKeys ak, BibTeX bt, AutoKorrektur auk, StenoData st) {
		// reference needed for fullscreen
		mainframe = this;

		dataObj = d;
		taskdata = td;
		desktopObj = dk;
		settingsObj = s;
		accKeys = ak;
		bibtexObj = bt;
		zknframe = zkn;
		spellObj = auk;
		stenoObj = st;
		bookmarksObj = bm;
		isLuhmannIconVisible = settingsObj.getShowLuhmannIconInDesktop();
		// check whether memory usage is logged. if so, tell logger that new entry
		// windows was opened
		if (settingsObj.isMemoryUsageLogged) {
			// log info
			Constants.zknlogger.log(Level.INFO, "Memory usage logged. Desktop Window opened.");
		}
		// create brushed look for window, so toolbar and window-bar become a unit
		if (settingsObj.isMacStyle()) {
			MacUtils.makeWindowLeopardStyle(getRootPane());
			// WindowUtils.createAndInstallRepaintWindowFocusListener(this);
			WindowUtils.installJComponentRepainterOnWindowFocusChanged(this.getRootPane());
		}
		// init all components
		initComponents();
		initListeners();
		initBorders(settingsObj);
		headingsVisibleMenuItem.setSelected(isHeadingVisible);
		entryNumberVisibleMenuItem.setSelected(isEntryNumberVisible);
		luhmannIconVisible.setSelected(isLuhmannIconVisible);
		// set application icon
		setIconImage(Constants.zknicon.getImage());
		// if we have mac os x with aqua, make the window look like typical
		// cocoa-applications
		if (settingsObj.isMacStyle()) {
			setupMacOSXLeopardStyle();
		}
		if (settingsObj.isSeaGlass()) {
			setupSeaGlassStyle();
		}
		// hide live-searchpanel on init.
		jPanelLiveSearch.setVisible(false);
		// retrieve system's line-separator
		lineseparator = System.lineSeparator();
		new TasksStatusBar(statusAnimationLabel, null, null);
		// set click to update-text
		jEditorPaneMain.setText(resourceMap.getString("clickToUpdateText"));
		jButtonShowMultipleOccurencesDlg.setVisible(false);
		// init the accelerator keys
		initAcceleratorTable();
		// This method initialises the toolbar buttons. depending on the user-setting,
		// we either
		// display small, medium or large icons as toolbar-icons.
		initToolbarIcons();
		// init jTree. we also initialise a DropTargetEvent here, so drag&drop-handling
		// is
		// completeley initiated in this method
		initTree();
		// init drag&drop-operations for editor-panes, so the user can drag&drop entries
		// from the jTree to the editorpanes...
		initDropPanes(jTextArea1);
		initDropPanes(jTextArea2);
		initDropPanes(jTextArea3);
		initComboBox();
		initDefaultFontSize();
		updateTitle();
	}

	private void initBorders(Settings settingsObj) {
		/*
		 * Constructor for Matte Border public MatteBorder(int top, int left, int
		 * bottom, int right, Color matteColor)
		 */
		jPanelLiveSearch.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, ColorUtil.getBorderGray(settingsObj)));
		if (settingsObj.isSeaGlass()) {
			jSplitPaneDesktop2
					.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, ColorUtil.getBorderGray(settingsObj)));
			jScrollPane1.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, ColorUtil.getBorderGray(settingsObj)));
			jTextArea1.setBorder(
					ZknMacWidgetFactory.getTitledBorder(resourceMap.getString("jTextArea1.border.title"), settingsObj));
			jTextArea2.setBorder(
					ZknMacWidgetFactory.getTitledBorder(resourceMap.getString("jTextArea2.border.title"), settingsObj));
			jTextArea3.setBorder(
					ZknMacWidgetFactory.getTitledBorder(resourceMap.getString("jTextArea3.border.title"), settingsObj));
		}
		if (settingsObj.isMacStyle()) {
			ZknMacWidgetFactory.updateSplitPane(jSplitPaneDesktop1);
			ZknMacWidgetFactory.updateSplitPane(jSplitPaneDesktop2);
			jTextArea1.setBorder(
					ZknMacWidgetFactory.getTitledBorder(resourceMap.getString("jTextArea1.border.title"), settingsObj));
			jTextArea2.setBorder(
					ZknMacWidgetFactory.getTitledBorder(resourceMap.getString("jTextArea2.border.title"), settingsObj));
			jTextArea3.setBorder(
					ZknMacWidgetFactory.getTitledBorder(resourceMap.getString("jTextArea3.border.title"), settingsObj));
		}
	}

	/**
	 *
	 */
	public final void updateTitle() {
		String currentTitle = getTitle();
		// get filename and find out where extension begins, so we can just set the
		// filename as title
		File f = settingsObj.getMainDataFile();
		// check whether we have any valid filepath at all
		if (f != null && f.exists()) {
			String fname = f.getName();
			// find file-extension
			int extpos = fname.lastIndexOf(Constants.ZKN_FILEEXTENSION);
			// set the filename as title
			if (extpos != -1) {
				// show proxy-icon, only applies to mac.
				getRootPane().putClientProperty("Window.documentFile", f);
				// set file-name and app-name in title-bar
				setTitle(currentTitle + " - [" + fname.substring(0, extpos) + "]");
			}
		}
	}

	/**
	 *
	 */
	private void initListeners() {
		// <editor-fold defaultstate="collapsed" desc="Here all relevant listeners are
		// initiated.">
		// these codelines add an escape-listener to the dialog. so, when the user
		// presses the escape-key, the same action is performed as if the user
		// presses the cancel button...
		KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
		ActionListener cancelAction = new java.awt.event.ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				quitFullScreen();
			}
		};
		getRootPane().registerKeyboardAction(cancelAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
		addWindowListener(this);
		// these code lines add an escape-listener to the dialog. so, when the user
		// presses the escape-key, the same action is performed as if the user
		// presses the cancel button...
		stroke = KeyStroke.getKeyStroke(accKeys.getAcceleratorKey(AcceleratorKeys.MAINKEYS, "showSearchResultWindow"));
		ActionListener showSearchResultsAction = new java.awt.event.ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				zknframe.showSearchResultWindow();
			}
		};
		getRootPane().registerKeyboardAction(showSearchResultsAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
		// these code lines add an escape-listener to the dialog. so, when the user
		// presses the escape-key, the same action is performed as if the user
		// presses the cancel button...
		stroke = KeyStroke.getKeyStroke(accKeys.getAcceleratorKey(AcceleratorKeys.MAINKEYS, "showNewEntryWindow"));
		ActionListener showNewEntryFrameAction = new java.awt.event.ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				zknframe.showNewEntryWindow();
			}
		};
		getRootPane().registerKeyboardAction(showNewEntryFrameAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
		// these code lines add an escape-listener to the dialog. so, when the user
		// presses the escape-key, the same action is performed as if the user
		// presses the cancel button...
		stroke = KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0);
		ActionListener showMainFrameAction = new java.awt.event.ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				zknframe.bringToFront();
			}
		};
		getRootPane().registerKeyboardAction(showMainFrameAction, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
		jTextArea1.addMouseListener(new java.awt.event.MouseAdapter() {
			@Override
			public void mousePressed(java.awt.event.MouseEvent evt) {
				if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) {
					jPopupMenuCutCopyPaste.show(jTextArea1, evt.getPoint().x, evt.getPoint().y);
				}
			}

			@Override
			public void mouseReleased(java.awt.event.MouseEvent evt) {
				if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) {
					jPopupMenuCutCopyPaste.show(jTextArea1, evt.getPoint().x, evt.getPoint().y);
				}
			}
		});
		jTextArea2.addMouseListener(new java.awt.event.MouseAdapter() {
			@Override
			public void mousePressed(java.awt.event.MouseEvent evt) {
				if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) {
					jPopupMenuCutCopyPaste.show(jTextArea2, evt.getPoint().x, evt.getPoint().y);
				}
			}

			@Override
			public void mouseReleased(java.awt.event.MouseEvent evt) {
				if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) {
					jPopupMenuCutCopyPaste.show(jTextArea2, evt.getPoint().x, evt.getPoint().y);
				}
			}
		});
		jTextArea3.addMouseListener(new java.awt.event.MouseAdapter() {
			@Override
			public void mousePressed(java.awt.event.MouseEvent evt) {
				if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) {
					jPopupMenuCutCopyPaste.show(jTextArea3, evt.getPoint().x, evt.getPoint().y);
				}
			}

			@Override
			public void mouseReleased(java.awt.event.MouseEvent evt) {
				if (evt.isPopupTrigger() && !jPopupMenuCutCopyPaste.isVisible()) {
					jPopupMenuCutCopyPaste.show(jTextArea3, evt.getPoint().x, evt.getPoint().y);
				}
			}
		});
		jTreeDesktop.addMouseListener(new java.awt.event.MouseAdapter() {
			@Override
			public void mousePressed(java.awt.event.MouseEvent evt) {
				if (evt.isPopupTrigger() && !jPopupMenuDesktop.isVisible()) {
					jPopupMenuDesktop.show(jTreeDesktop, evt.getPoint().x, evt.getPoint().y);
				}
			}

			@Override
			public void mouseReleased(java.awt.event.MouseEvent evt) {
				if (evt.isPopupTrigger() && !jPopupMenuDesktop.isVisible()) {
					jPopupMenuDesktop.show(jTreeDesktop, evt.getPoint().x, evt.getPoint().y);
				}
			}

			@Override
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				// this listener should only react on left-mouse-button-clicks...
				// if other button then left-button clicked, leeave...
				if (evt.getButton() == MouseEvent.BUTTON1 && 2 == evt.getClickCount()) {
					modifiyEntry();
				}
			}
		});
		jTreeDesktop.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
			@Override
			public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
				updateToolbarAndMenu();
				scrollToEntry();
			}
		});
		jTreeDesktop.addTreeExpansionListener(new javax.swing.event.TreeExpansionListener() {
			@Override
			public void treeExpanded(javax.swing.event.TreeExpansionEvent evt) {
				changeBulletTreefold(evt, true);
			}

			@Override
			public void treeCollapsed(javax.swing.event.TreeExpansionEvent evt) {
				changeBulletTreefold(evt, false);
			}
		});
		jEditorPaneMain.addMouseListener(new java.awt.event.MouseAdapter() {
			@Override
			public void mouseClicked(java.awt.event.MouseEvent evt) {
				updateView();
			}
		});
		jEditorPaneMain.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
			@Override
			public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
				// retrieve the event type, e.g. if a link was clicked by the user
				HyperlinkEvent.EventType typ = evt.getEventType();
				// get the description, to check whether we have a file or a hyperlink to a
				// website
				String linktype = evt.getDescription();
				// if the link was clicked, proceed
				if (typ == HyperlinkEvent.EventType.ACTIVATED) {
					// call method that handles the hyperlink-click
					String returnValue = Tools.openHyperlink(linktype, mainframe, Constants.FRAME_DESKTOP, dataObj,
							bibtexObj, settingsObj, jEditorPaneMain, -1);
					// check whether we have a return value. this might be the case either when the
					// user clicked on
					// a footenote, or on the rating-stars
					if (returnValue != null && returnValue.startsWith("#z_")) {
						// show entry
						zknframe.setNewActivatedEntryAndUpdateDisplay(dataObj.getActivatedEntryNumber());
					}
				} else if (evt.getEventType() == HyperlinkEvent.EventType.ENTERED) {
					javax.swing.text.Element elem = evt.getSourceElement();
					if (elem != null) {
						AttributeSet attr = elem.getAttributes();
						AttributeSet a = (AttributeSet) attr.getAttribute(HTML.Tag.A);
						if (a != null) {
							jEditorPaneMain.setToolTipText((String) a.getAttribute(HTML.Attribute.TITLE));
						}
					}
				} else if (evt.getEventType() == HyperlinkEvent.EventType.EXITED) {
					jEditorPaneMain.setToolTipText(null);
				}
			}
		});

		jTextFieldLiveSearch.addKeyListener(new java.awt.event.KeyAdapter() {
			@Override
			public void keyReleased(java.awt.event.KeyEvent evt) {
				// when the user presses the escape-key, hide panel
				if (KeyEvent.VK_ESCAPE == evt.getKeyCode()) {
					findCancel();
				} // when up/down arrows are pressed, find next/previous occurence of search term
				else if (Tools.isNavigationKey(evt.getKeyCode())) {
					switch (evt.getKeyCode()) {
					// if user pressed arrow down key, find next occurence of live search
					case KeyEvent.VK_DOWN:
						findLiveNext();
						break;
					// if user pressed arrow down key, find previous occurence of live search
					case KeyEvent.VK_UP:
						findLivePrev();
						break;
					}
				} // when user presses enter key, retrieve new search term and highlight term
				else if (KeyEvent.VK_ENTER == evt.getKeyCode() && jTextFieldLiveSearch.getText().length() > 1) {
					updateLiveSearchDisplay();
				}
			}
		});
		//
		// init the menu-listeners...
		//
		desktopMenuFile.addMenuListener(new javax.swing.event.MenuListener() {
			@Override
			public void menuSelected(javax.swing.event.MenuEvent evt) {
				exportMultipleMenuItem.setEnabled(desktopObj.getCount() > 1);
			}

			@Override
			public void menuDeselected(javax.swing.event.MenuEvent evt) {
			}

			@Override
			public void menuCanceled(javax.swing.event.MenuEvent evt) {
			}
		});
		desktopMenuView.addMenuListener(new javax.swing.event.MenuListener() {
			@Override
			public void menuSelected(javax.swing.event.MenuEvent evt) {
				// set selected state
				showDesktopTreeEntryNumberMenuItem.setSelected(settingsObj.getShowDesktopEntryNumber());
				// check whether we have any comments at all
				if (!desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement())) {
					// if not, disable menu item
					jRadioButtonDesktopOnlyComments.setEnabled(false);
					// if view option was comments only, change this option
					if (Constants.DESKTOP_ONLY_COMMENTS == settingsObj.getDesktopCommentDisplayOptions()) {
						settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITH_COMMENTS);
					}
				} else {
					jRadioButtonDesktopOnlyComments.setEnabled(true);
				}
				switch (settingsObj.getDesktopCommentDisplayOptions()) {
				case Constants.DESKTOP_WITH_COMMENTS:
					jRadioButtonDesktopWithComment.setSelected(true);
					break;
				case Constants.DESKTOP_WITHOUT_COMMENTS:
					jRadioButtonDesktopWithoutComments.setSelected(true);
					break;
				case Constants.DESKTOP_ONLY_COMMENTS:
					jRadioButtonDesktopOnlyComments.setSelected(true);
					break;
				default:
					jRadioButtonDesktopWithComment.setSelected(true);
					break;
				}
			}

			@Override
			public void menuDeselected(javax.swing.event.MenuEvent evt) {
			}

			@Override
			public void menuCanceled(javax.swing.event.MenuEvent evt) {
			}
		});

		// </editor-fold>
	}

	/**
	 * This method changes a bullet-point's treefold-state, so it's remembered when
	 * re-building the treeview.
	 *
	 * @param evt        the {@code TreeExpansionEvent} which holds information
	 *                   about the node that was expanded or collapsed
	 * @param isExpanded {@code true} if the node was expandend, {@code false} if it
	 *                   was collapsed. This information is retrieved from the
	 *                   {@code addTreeExpansionListener}, see
	 *                   {@link #initListeners() initListeners()}.
	 */
	private void changeBulletTreefold(javax.swing.event.TreeExpansionEvent evt, boolean isExpanded) {
		// retrieve path of value that was expanded
		TreePath tp = evt.getPath();
		// check whether root was expanded or not. therefore, retrieve root-node
		// and the last node of the treepath, i.e. the node which was expanded
		TreeNode root = (TreeNode) jTreeDesktop.getModel().getRoot();
		TreeNode expandednode = (TreeNode) tp.getLastPathComponent();
		// if they equal, do nothing
		if (expandednode.equals(root) || TreeUtil.nodeIsRoot((DefaultMutableTreeNode) expandednode)) {
			return;
		}
		// else, retrieve node's timestamp
		String timestamp = TreeUtil.getNodeTimestamp((DefaultMutableTreeNode) tp.getLastPathComponent());
		// and set new treefold-state
		desktopObj.setBulletTreefold(timestamp, isExpanded);
	}

	/**
	 * This method initiates the drag&drop-hanlding for the jEditorPanes. By doing
	 * this, the user can drag entries from the jTree to the editorpane(s), and the
	 * entry's content will be displayed in that editorpane. it's just a more
	 * comfortable way to handle the notes a user can make when working with the
	 * outliner-feature - in case the user wants to keep entries permanently
	 * visible, this feature can be used.
	 *
	 * @param editorpane an existing jEditorPane, in this case we use the components
	 *                   {@code jEditorPaneS1}, {@code jEditorPaneS2} and
	 *                   {@code jEditorPaneS3}
	 */
	private void initDropPanes(final javax.swing.JTextArea editorpane) {
		editorpane.setTransferHandler(new EntryStringTransferHandler() {
			@Override
			protected String exportString(JComponent c) {
				return editorpane.getSelectedText();
			}

			@Override
			protected boolean importString(JComponent c, String str) {
				// check for valid drop-string
				if (str != null) {
					// each received string consists of two lines. the first one with information
					// about the drag-source and the drag-operation, the second one with the data
					// by this we can see whether we have received entries (i.e. a valid drop)
					String[] dropinformation = str.split("\n");
					// get source information
					String[] sourceinfo = dropinformation[0].split(",");
					// check out the source of the drag-operation. if we have a valid source,
					// retrieve entries than.
					if (sourceinfo.length > 1 && sourceinfo[1].equals(Constants.DRAG_SOURCE_TYPE_ENTRIES)) {
						// we only accept drop-data from tables, so we might have several
						// lines, separates by a new-line. thus, split all new lines into
						// a string array.
						String[] entries = dropinformation[1].split(",");
						// if we have any dropped data, go on...
						if (entries != null && entries.length > 0) {
							// get converted entry
							StringBuilder text = new StringBuilder();
							for (String entrie : entries) {
								try {
									text.append(dataObj.getZettelContentAsHtml(Integer.parseInt(entrie)));
									text.append(lineseparator);
								} catch (NumberFormatException | IndexOutOfBoundsException ex) {
								}
							}
							// add content to editor pane
							editorpane.setText(text.toString());
						}
						return true;
					} else {
						editorpane.append(str);
					}
				}
				return false;
			}

			@Override
			protected void cleanup(JComponent c, boolean remove) {
			}
		});
	}

	/**
	 * This method initialises the toolbar buttons. depending on the user-setting,
	 * we either display small, medium or large icons as toolbar-icons.
	 */
	public final void initToolbarIcons() {
		// check whether the toolbar should be displayed at all...
		if (!settingsObj.getShowIcons() && !settingsObj.getShowIconText()) {
			// if not, hide it and leave.
			jToolBarDesktop.setVisible(false);
			// and set a border to the main panel, because the toolbar's dark border is
			// hidden
			// and remove border from the main panel
			jPanel1.setBorder(new MatteBorder(1, 0, 0, 0, ColorUtil.colorDarkLineGray));
			return;
		}
		// set toolbar visible
		jToolBarDesktop.setVisible(true);
		// and remove border from the main panel
		jPanel1.setBorder(null);
		// init toolbar button array
		javax.swing.JButton[] toolbarButtons = new javax.swing.JButton[] { tb_newbullet, tb_newentry, tb_modifyentry,
				tb_cut, tb_copy, tb_paste, tb_rename, tb_comment, tb_delete, tb_refresh, tb_addluhmann, tb_moveup,
				tb_movedown };
		String[] buttonNames = new String[] { "tb_newbulletText", "tb_newdesktopentryText", "tb_editText", "tb_cutText",
				"tb_copyText", "tb_pasteText", "tb_renameText", "tb_commentText", "tb_deleteText", "tb_refreshText",
				"tb_addluhmannText", "tb_moveupText", "tb_movedownText" };
		String[] iconNames = new String[] { "newBulletIcon", "newDesktopEntryIcon", "editEntryIcon", "cutIcon",
				"copyIcon", "pasteIcon", "renameBulletIcon", "commentNodeIcon", "deleteIcon", "updateViewIcon",
				"addLuhmannIcon", "moveNodeUpIcon", "moveNodeDownIcon" };
		// set toolbar-icons' text
		if (settingsObj.getShowIconText()) {
			for (int cnt = 0; cnt < toolbarButtons.length; cnt++) {
				toolbarButtons[cnt].setText(toolbarResourceMap.getString(buttonNames[cnt]));
			}
		} else {
			for (javax.swing.JButton tbb : toolbarButtons) {
				tbb.setText("");
			}
		}
		// show icons, if requested
		if (settingsObj.getShowIcons()) {
			// retrieve icon theme path
			String icontheme = settingsObj.getIconThemePath();
			for (int cnt = 0; cnt < toolbarButtons.length; cnt++) {
				toolbarButtons[cnt].setIcon(new ImageIcon(
						ZettelkastenView.class.getResource(icontheme + toolbarResourceMap.getString(iconNames[cnt]))));
			}
		} else {
			for (javax.swing.JButton tbb : toolbarButtons) {
				tbb.setIcon(null);
			}
		}
		if (!settingsObj.getShowAllIcons()) {
			tb_addluhmann.setVisible(false);
			tb_rename.setVisible(false);
		}
		if (settingsObj.isMacStyle()) {
			makeMacToolbar();
		}
		if (settingsObj.isSeaGlass()) {
			makeSeaGlassToolbar();
		}
	}

	private void setupSeaGlassStyle() {
		getRootPane().setBackground(ColorUtil.colorSeaGlassGray);
		jTextFieldLiveSearch.putClientProperty("JTextField.variant", "search");
		jEditorPaneMain.setBackground(Color.white);
	}

	/**
	 * This method applies some graphical stuff so the appearance of the program is
	 * even more mac-like...
	 */
	private void setupMacOSXLeopardStyle() {

		MacWidgetFactory.makeEmphasizedLabel(jLabel1);
		// get the toolbar-action
		AbstractAction ac = (AbstractAction) org.jdesktop.application.Application
				.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext()
				.getActionMap(DesktopFrame.class, this).get("findCancel");
		// and change the large-icon-property, which is applied to the toolbar-icons,
		// to the new icon
		ac.putValue(AbstractAction.LARGE_ICON_KEY,
				new ImageIcon(Toolkit.getDefaultToolkit().getImage("NSImage://NSStopProgressFreestandingTemplate")
						.getScaledInstance(16, 16, Image.SCALE_SMOOTH)));
		ac.putValue(AbstractAction.SMALL_ICON,
				new ImageIcon(Toolkit.getDefaultToolkit().getImage("NSImage://NSStopProgressFreestandingTemplate")
						.getScaledInstance(16, 16, Image.SCALE_SMOOTH)));
		// </editor-fold>
	}

	private void makeSeaGlassToolbar() {
		Tools.makeTexturedToolBarButton(tb_newbullet, Tools.SEGMENT_POSITION_FIRST);
		if (settingsObj.getShowAllIcons()) {
			Tools.makeTexturedToolBarButton(tb_newentry, Tools.SEGMENT_POSITION_MIDDLE);
			Tools.makeTexturedToolBarButton(tb_addluhmann, Tools.SEGMENT_POSITION_LAST);
		} else {
			Tools.makeTexturedToolBarButton(tb_newentry, Tools.SEGMENT_POSITION_LAST);
		}
		Tools.makeTexturedToolBarButton(tb_modifyentry, Tools.SEGMENT_POSITION_FIRST);
		Tools.makeTexturedToolBarButton(tb_cut, Tools.SEGMENT_POSITION_MIDDLE);
		Tools.makeTexturedToolBarButton(tb_copy, Tools.SEGMENT_POSITION_MIDDLE);
		Tools.makeTexturedToolBarButton(tb_paste, Tools.SEGMENT_POSITION_LAST);
		Tools.makeTexturedToolBarButton(tb_moveup, Tools.SEGMENT_POSITION_FIRST);
		Tools.makeTexturedToolBarButton(tb_movedown, Tools.SEGMENT_POSITION_LAST);
		if (settingsObj.getShowAllIcons()) {
			Tools.makeTexturedToolBarButton(tb_rename, Tools.SEGMENT_POSITION_FIRST);
			Tools.makeTexturedToolBarButton(tb_comment, Tools.SEGMENT_POSITION_MIDDLE);
		} else {
			Tools.makeTexturedToolBarButton(tb_comment, Tools.SEGMENT_POSITION_FIRST);
		}
		Tools.makeTexturedToolBarButton(tb_delete, Tools.SEGMENT_POSITION_LAST);
		Tools.makeTexturedToolBarButton(tb_refresh, Tools.SEGMENT_POSITION_ONLY);
		jToolBarDesktop.setPreferredSize(
				new java.awt.Dimension(jToolBarDesktop.getSize().width, Constants.seaGlassToolbarHeight));
		jToolBarDesktop.add(new javax.swing.JToolBar.Separator(), 0);
	}

	private void makeMacToolbar() {
		// hide default toolbr
		jToolBarDesktop.setVisible(false);
		this.remove(jToolBarDesktop);
		// and create mac toolbar
		if (settingsObj.getShowIcons() || settingsObj.getShowIconText()) {

			UnifiedToolBar mactoolbar = new UnifiedToolBar();

			mactoolbar.addComponentToLeft(
					MacToolbarButton.makeTexturedToolBarButton(tb_newbullet, MacToolbarButton.SEGMENT_POSITION_FIRST));
			if (settingsObj.getShowAllIcons()) {
				mactoolbar.addComponentToLeft(MacToolbarButton.makeTexturedToolBarButton(tb_newentry,
						MacToolbarButton.SEGMENT_POSITION_MIDDLE));
				mactoolbar.addComponentToLeft(MacToolbarButton.makeTexturedToolBarButton(tb_addluhmann,
						MacToolbarButton.SEGMENT_POSITION_LAST));
			} else {
				mactoolbar.addComponentToLeft(MacToolbarButton.makeTexturedToolBarButton(tb_newentry,
						MacToolbarButton.SEGMENT_POSITION_LAST));
			}
			mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1));
			mactoolbar.addComponentToLeft(MacToolbarButton.makeTexturedToolBarButton(tb_modifyentry,
					MacToolbarButton.SEGMENT_POSITION_FIRST));
			mactoolbar.addComponentToLeft(
					MacToolbarButton.makeTexturedToolBarButton(tb_cut, MacToolbarButton.SEGMENT_POSITION_MIDDLE));
			mactoolbar.addComponentToLeft(
					MacToolbarButton.makeTexturedToolBarButton(tb_copy, MacToolbarButton.SEGMENT_POSITION_MIDDLE));
			mactoolbar.addComponentToLeft(
					MacToolbarButton.makeTexturedToolBarButton(tb_paste, MacToolbarButton.SEGMENT_POSITION_LAST));
			mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1));
			mactoolbar.addComponentToLeft(
					MacToolbarButton.makeTexturedToolBarButton(tb_moveup, MacToolbarButton.SEGMENT_POSITION_FIRST));
			mactoolbar.addComponentToLeft(
					MacToolbarButton.makeTexturedToolBarButton(tb_movedown, MacToolbarButton.SEGMENT_POSITION_LAST));
			mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1));
			if (settingsObj.getShowAllIcons()) {
				mactoolbar.addComponentToLeft(
						MacToolbarButton.makeTexturedToolBarButton(tb_rename, MacToolbarButton.SEGMENT_POSITION_FIRST));
				mactoolbar.addComponentToLeft(MacToolbarButton.makeTexturedToolBarButton(tb_comment,
						MacToolbarButton.SEGMENT_POSITION_MIDDLE));
			} else {
				mactoolbar.addComponentToLeft(MacToolbarButton.makeTexturedToolBarButton(tb_comment,
						MacToolbarButton.SEGMENT_POSITION_FIRST));
			}
			mactoolbar.addComponentToLeft(
					MacToolbarButton.makeTexturedToolBarButton(tb_delete, MacToolbarButton.SEGMENT_POSITION_LAST));
			mactoolbar.addComponentToLeft(MacWidgetFactory.createSpacer(16, 1));
			mactoolbar.addComponentToLeft(
					MacToolbarButton.makeTexturedToolBarButton(tb_refresh, MacToolbarButton.SEGMENT_POSITION_ONLY));

			mactoolbar.installWindowDraggerOnWindow(this);
			jPanel1.add(mactoolbar.getComponent(), BorderLayout.PAGE_START);
		}
		makeMacBottomBar();
	}

	private void makeMacBottomBar() {
		jPanel7.setVisible(false);

		BottomBar macbottombar = new BottomBar(BottomBarSize.LARGE);
		macbottombar.addComponentToLeft(MacWidgetFactory.makeEmphasizedLabel(jLabel1));
		macbottombar.addComponentToLeft(jComboBoxDesktop);
		macbottombar.addComponentToLeft(MacWidgetFactory.makeEmphasizedLabel(jLabelWordCount));
		macbottombar.addComponentToLeft(jButtonShowMultipleOccurencesDlg);
		macbottombar.addComponentToRight(statusAnimationLabel);

		jPanel2.remove(jPanel7);
		jPanel2.setBorder(null);
		jPanel2.setLayout(new BorderLayout());
		jPanel2.add(macbottombar.getComponent(), BorderLayout.PAGE_START);
	}

	/**
	 * This method sets the default font-size for tables, lists and treeviews. If
	 * the user wants to have bigger font-sizes for better viewing, the new
	 * font-size will be applied to the components here.
	 */
	private void initDefaultFontSize() {
		// get the default fontsize for tables and lists
		int defaultsize = settingsObj.getDesktopOutlineFontSize();
		// get current font
		int fsize = jTreeDesktop.getFont().getSize();
		// retrieve default listvewfont
		Font defaultfont = settingsObj.getDesktopOutlineFont();
		// create new font, add fontsize-value
		Font f = new Font(defaultfont.getName(), defaultfont.getStyle(), fsize + defaultsize);
		// set new font
		jTreeDesktop.setFont(f);
	}

	/**
	 * This method sets the accelerator table for all relevant actions which should
	 * have accelerator keys. We don't use the GUI designer to set the values,
	 * because the user should have the possibility to define own accelerator keys,
	 * which are managed within the CAcceleratorKeys-class and loaed/saved via the
	 * CSettings-class
	 */
	private void initAcceleratorTable() {
		// setting up the accelerator table. we have two possibilities: either assigning
		// accelerator keys directly with an action like this:
		//
		// javax.swing.ActionMap actionMap =
		// org.jdesktop.application.Application.getInstance(zettelkasten.ZettelkastenApp.class).getContext().getActionMap(ZettelkastenView.class,
		// this);
		// AbstractAction ac = (AbstractAction) actionMap.get("newEntry");
		// KeyStroke controlN = KeyStroke.getKeyStroke("control N");
		// ac.putValue(AbstractAction.ACCELERATOR_KEY, controlN);
		//
		// or setting the accelerator key directly to a menu-item like this:
		//
		// newEntryMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
		// InputEvent.META_MASK));
		//
		// we choose the first option, because so we can easily iterate through the xml
		// file
		// and retrieve action names as well as accelerator keys. this saves a lot of
		// typing work here
		//
		// get the action map
		javax.swing.ActionMap actionMap = org.jdesktop.application.Application
				.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).getContext()
				.getActionMap(DesktopFrame.class, this);
		// iterate the xml file with the accelerator keys for the main window
		for (int cnt = 1; cnt <= accKeys.getCount(AcceleratorKeys.DESKTOPKEYS); cnt++) {
			// get the action's name
			String actionname = accKeys.getAcceleratorAction(AcceleratorKeys.DESKTOPKEYS, cnt);
			// check whether we have found any valid action name
			if (actionname != null && !actionname.isEmpty()) {
				// retrieve action
				AbstractAction ac = (AbstractAction) actionMap.get(actionname);
				// get the action's accelerator key
				String actionkey = accKeys.getAcceleratorKey(AcceleratorKeys.DESKTOPKEYS, cnt);
				// check whether we have any valid actionkey
				if (actionkey != null && !actionkey.isEmpty()) {
					// retrieve keystroke setting
					KeyStroke ks = KeyStroke.getKeyStroke(actionkey);
					// and put them together :-)
					ac.putValue(AbstractAction.ACCELERATOR_KEY, ks);
				}
			}
		}
		// now set the mnemonic keys of the menus (i.e. the accelerator keys, which give
		// access
		// to the menu via "alt"+key). since the menus might have different texts,
		// depending on
		// the programs language, we retrieve the menu text and simply set the first
		// char
		// as mnemonic key
		// ATTENTION! Mnemonic keys are NOT applied on Mac OS, see Apple guidelines for
		// further details:
		// http://developer.apple.com/DOCUMENTATION/Java/Conceptual/Java14Development/07-NativePlatformIntegration/NativePlatformIntegration.html#//apple_ref/doc/uid/TP40001909-211867-BCIBDHFJ
		if (!settingsObj.isMacStyle()) {
			// init the variables
			String menutext;
			char mkey;
			// the mnemonic key for the file menu
			menutext = desktopMenuFile.getText();
			mkey = menutext.charAt(0);
			desktopMenuFile.setMnemonic(mkey);
			// the mnemonic key for the edit menu
			menutext = desktopMenuEdit.getText();
			mkey = menutext.charAt(0);
			desktopMenuEdit.setMnemonic(mkey);
			// the mnemonic key for the view menu
			menutext = desktopMenuView.getText();
			mkey = menutext.charAt(0);
			desktopMenuView.setMnemonic(mkey);
		}
		// on Mac OS, at least for the German locale, the File menu is called different
		// compared to windows or linux. Furthermore, we don't need the about and
		// preferences
		// menu items, since these are locates on the program's menu item in the
		// apple-menu-bar
		if (PlatformUtil.isMacOS()) {
			desktopMenuFile.setText(resourceMap.getString("macFileMenuText"));
		}
		// en- or disable fullscreen icons
		setFullScreenSupp(graphicdevice.isFullScreenSupported());
		// if fullscreen is not supportet, tell this in the tooltip
		if (!graphicdevice.isFullScreenSupported()) {
			AbstractAction ac = (AbstractAction) actionMap.get("viewFullScreen");
			ac.putValue(AbstractAction.SHORT_DESCRIPTION, resourceMap.getString("fullScreenNotSupported"));
		}
		// jTrees have their own input-map, so we have to re-assign the
		// standard-shortcuts for
		// the jTree here... otherwise, copying nodes would lead to copy just the node's
		// text,
		// and not - as we are intending - the node itself...
		String[] treeactions = new String[] { "cutNode", "copyNode", "pasteNode", "renameBullet", "moveNodeUp",
				"moveNodeDown" };
		// iterate the actions-array and change input-map for all relevant actions in
		// the jTree
		for (String tac : treeactions) {
			// change tree's action-map for cut-action
			jTreeDesktop.getActionMap().put(tac + "KeyPressed", actionMap.get(tac));
			// associate new keystroke with that action
			KeyStroke ks = KeyStroke.getKeyStroke(accKeys.getAcceleratorKey(AcceleratorKeys.DESKTOPKEYS, tac));
			// and put the new keystroke-value to the tree's input-map
			jTreeDesktop.getInputMap().put(ks, tac + "KeyPressed");
		}
	}

	/**
	 * This method inits the combobox. First it clears all existing items, then it
	 * adds all available desktop-data and finally an actionlistener is added to the
	 * jcombobox, that updates the display each time another desktop is chosen.
	 */
	private void initComboBox() {
		// clear combobox
		jComboBoxDesktop.removeAllItems();
		// fill combo box, if we have any items at all
		if (desktopObj.getCount() > 0) {
			// go through all desktops and add their names to the combobox
			for (int cnt = 0; cnt < desktopObj.getCount(); cnt++) {
				jComboBoxDesktop.addItem(desktopObj.getDesktopName(cnt));
			}
			// add action listener
			addCbActionListener();
			// select first item
			jComboBoxDesktop.setSelectedIndex(settingsObj.getLastUsedDesktop(desktopObj.getCount()));
		}
	}

	/**
	 * This method inits the action listener for the combo box.
	 */
	private void addCbActionListener() {
		// add action listener to combo box
		jComboBoxDesktop.addActionListener(new java.awt.event.ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				// save current notes
				desktopObj.setDesktopNotes(1, jTextArea1.getText());
				desktopObj.setDesktopNotes(2, jTextArea2.getText());
				desktopObj.setDesktopNotes(3, jTextArea3.getText());
				// after that, set the new selected index as current desktop index
				desktopObj.setCurrentDesktopNr(jComboBoxDesktop.getSelectedIndex());
				// update the treeview, i.e. fill it with outline/structure from
				// the xml-document
				updateTreeView();
				// if view option was comments only, change this option if we don't have any
				// comments at all
				if (Constants.DESKTOP_ONLY_COMMENTS == settingsObj.getDesktopCommentDisplayOptions()
						&& !desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement())) {
					settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITH_COMMENTS);
				}
				// tell the user that he should click to update...
				jEditorPaneMain.setText(resourceMap.getString("clickToUpdateText"));
				// init notes, if any
				jTextArea1.setText(desktopObj.getDesktopNotes(1));
				jTextArea2.setText(desktopObj.getDesktopNotes(2));
				jTextArea3.setText(desktopObj.getDesktopNotes(3));
				setNeedsUpdate(true);
			}
		});
	}

	/**
	 * Toggles the visibility of the notes-sidebar, i.e. either collapses or expands
	 * the splitpane on demand.
	 */
	@Action
	public void toggleNotesVisibility() {
		isSidebarHidden = !isSidebarHidden;
		if (isSidebarHidden) {
			setSplitLocation(jSplitPaneDesktop2.getDividerLocation());
			jSplitPaneDesktop2.setDividerLocation(1.0d);
		} else {
			int pos = getSplitLocation();
			if (-1 == pos) {
				pos = mainframe.getWidth() - Constants.MIN_SIDEBAR_SIZE;
			}
			jSplitPaneDesktop2.setDividerLocation(pos);
		}
	}

	private int savedDividerLocation = 0;

	private void setSplitLocation(int pos) {
		savedDividerLocation = pos;
	}

	private int getSplitLocation() {
		return savedDividerLocation;
	}

	@Action
	public void printContent() {
		javax.swing.JEditorPane tmpPane = new javax.swing.JEditorPane();
		tmpPane.setEditorKit(jEditorPaneMain.getEditorKit());
		tmpPane.setContentType(jEditorPaneMain.getContentType());
		StringBuilder sb = new StringBuilder();
		sb.append(completePage);
		// if we have any content, insert html-header at the beginning...
		if (sb.length() > 0) {
			sb.insert(0, HtmlUbbUtil.getHtmlHeaderForDesktop(settingsObj, true));
		}
		tmpPane.setText(sb.toString());
		try {
			tmpPane.print();
		} catch (PrinterException e) {
			Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage());
		}
	}

	/**
	 * Displays the selected entry in the main frame.
	 */
	@Action(enabledProperty = "entryNodeSelected")
	public void displayEntryInMainframe() {
		// retrieve selection from jTree
		int nr = getSelectedEntryNumber();
		// when we have a valid selection, go on
		if (nr != -1) {
			zknframe.setNewActivatedEntryAndUpdateDisplay(nr);
		}
	}

	public void showEntryInDesktop(int entrynr) {
		// check for valid value
		if (-1 == entrynr) {
			return;
		}
		// itereate all desktops
		for (int cnt = 0; cnt < desktopObj.getCount(); cnt++) {
			// check whether entry is in this desktop
			if (desktopObj.isEntryInDesktop(entrynr, cnt)) {
				// set entry number
				displayentrynr = entrynr;
				// selecte desktop
				jComboBoxDesktop.setSelectedIndex(cnt);
				// quit method
				return;
			}
		}
	}

	@Action
	public void showDesktopEntryNumber() {
		boolean val = settingsObj.getShowDesktopEntryNumber();
		settingsObj.setShowDesktopEntryNumber(!val);
		val = isNeedsUpdate();
		updateTreeView();
		if (!val) {
			setNeedsUpdate(false);
		}
	}

	/**
	 * Each time we add/delete a desktop, the combo box is being updated. First,
	 * this method checks whether the current desktop was modified or not, and saves
	 * the current desktop-data to xml-file, if necessary. <br>
	 * <br>
	 * Then all action listeners are removed, so no actionevent is fired when we add
	 * new items to the combobox. Then all available desktop-data is added. Finally,
	 * an actionlistener is added to the jcombobox, that updates the display each
	 * time another desktop is chosen.
	 *
	 * @param closing true when the window will be closed, false if the combobox
	 *                should be updated and the desktop-window will not be closed.
	 */
	private void updateComboBox(boolean closing) {
		// get all action listeners from the combo box
		ActionListener[] al = jComboBoxDesktop.getActionListeners();
		// remove all action listeners so we don't fire several action-events
		// when we update the combo box. we can set the action listener later again
		for (ActionListener listener : al) {
			jComboBoxDesktop.removeActionListener(listener);
		}
		// clear combobox
		jComboBoxDesktop.removeAllItems();
		// add all desktop-items to combo-box
		for (int cnt = 0; cnt < desktopObj.getCount(); cnt++) {
			jComboBoxDesktop.addItem(desktopObj.getDesktopName(cnt));
		}
		// add action listener to combo box
		addCbActionListener();
		// enable multiple-export-menu-item
		exportMultipleMenuItem.setEnabled(desktopObj.getCount() > 1);
		// select last item
		if (!closing) {
			try {
				jComboBoxDesktop.setSelectedIndex(jComboBoxDesktop.getItemCount() - 1);
			} catch (IllegalArgumentException e) {
			}
		}
	}

	/**
	 * A simple initialisation of the jTreeDesktop, i.e. the tree is cleared and
	 * single-selection-mode is set.
	 */
	private void initTree() {
		// get the treemodel
		DefaultTreeModel dtm = (DefaultTreeModel) jTreeDesktop.getModel();
		// and first of all, clear the jTree
		dtm.setRoot(null);
		// macstyle beim jTree setzen
		if (settingsObj.isMacStyle()) {
			jTreeDesktop.setUI(new MacSourceDesktopTree(desktopObj, dataObj, settingsObj));
		} else {
			// set cell renderer, for desktop icons
			jTreeDesktop.setCellRenderer(new MyCommentRenderer(Constants.iconDesktopComment,
					Constants.iconDesktopLuhmann, settingsObj.getUseMacBackgroundColor()));
			if (settingsObj.getUseMacBackgroundColor()) {
				jTreeDesktop.setBackground(ColorUtil.colorJTreeLighterBackground);
				jTreeDesktop.setForeground(ColorUtil.colorJTreeDarkText);
			}
			// set tree-selection-mode
			jTreeDesktop.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		}
		// enable drag&drop
		jTreeDesktop.setDragEnabled(true);
		// init transfer handler for tree
		jTreeDesktop.setTransferHandler(new EntryStringTransferHandler() {
			@Override
			protected String exportString(JComponent c) {
				// retrieve tree-component
				javax.swing.JTree t = (javax.swing.JTree) c;
				// retrieve selected node that was dragged
				DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) t.getSelectionPath()
						.getLastPathComponent();
				// prepare export-string, telling that the drag-source is the jTreeDesktop
				StringBuilder retval = new StringBuilder(Constants.DRAG_SOURCE_JTREEDESKTOP + ",");
				// and give information whether the dragged entry is a bullet or an entry
				retval.append((selectedNode.getAllowsChildren()) ? Constants.DRAG_SOURCE_TYPE_BULLET + "\n"
						: Constants.DRAG_SOURCE_TYPE_ENTRIES + "\n");
				// next line contains the entry-number, or -1 if a bullet was selected
				retval.append(getSelectedEntryNumber()).append("\n");
				// retrieve treepath of dragged entry/bullet
				TreePath tp = t.getSelectionPath();
				// add each single path component to return string, new-line-separated
				for (int cnt = 1; cnt < tp.getPathCount(); cnt++) {
					retval.append(tp.getPathComponent(cnt).toString()).append("\n");
				}
				// finally, add node-ID to string-information
				retval.append(TreeUtil.getNodeTimestamp(selectedNode));
				// remember selected node, which should be removed when dropping the node.
				movedNodeToRemove = selectedNode;
				// return information
				return retval.toString();
			}

			@Override
			protected boolean importString(JComponent c, String str) {
				// get drop-component, i.e. the jTreeDesktop
				javax.swing.JTree t = (javax.swing.JTree) c;
				// retrieve selected node
				DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) t.getSelectionPath()
						.getLastPathComponent();
				// check for valid drop-string
				if (str != null && selectedNode != null) {
					// retrieve nodetimestamp
					String nodets = TreeUtil.getNodeTimestamp(selectedNode);
					// each received string consists of two lines. the first one with information
					// about the drag-source and the drag-operation, the second one with the data
					// by this we can see whether we have received entries (i.e. a valid drop)
					String[] dropinformation = str.split("\n");
					// get source information
					String[] sourceinfo = dropinformation[0].split(",");
					// in case an edited entry has been dragged, remember
					// modifications and comment
					String modifications = null;
					String comment = null;
					// check out the source of the drag-operation. if we have a valid source,
					// retrieve entries.
					// here we have
					// - entries as drop-elements
					// - and no root selected, i.e. a valid drop-location
					if (sourceinfo.length > 1 && sourceinfo[1].equals(Constants.DRAG_SOURCE_TYPE_ENTRIES)
							&& !selectedNode.isRoot()) {
						// check for self-drop
						if (TreeUtil.getNodeTimestamp(movedNodeToRemove).equals(nodets)) {
							return false;
						}
						// here we have the jTreeDesktop as drag-source, i.e. a drag&drop from within
						// the jDesktopComponent. that means, we have to delete the drag-source, i.e.
						// the dragged node that was moved to the new location
						if (sourceinfo[0].equals(Constants.DRAG_SOURCE_JTREEDESKTOP)) {
							// retrieve node timestamp
							String ts = dropinformation[dropinformation.length - 1];
							// save modifications and comment
							modifications = desktopObj.retrieveModifiedEntryContentFromTimestamp(ts);
							comment = desktopObj.getComment(ts, "[br]");
							// delete entry
							desktopObj.deleteEntry(ts);
							// and remove node from original position
							movedNodeToRemove.removeFromParent();
						}
						// retrieve dropped entries. double entries are removed. if an entry comes from
						// within
						// the desktop, we have to check whether the dragged entry was just moved within
						// a
						// bullet. if so, we don't have to consider it as "double" entry.
						String entries = retrieveDropEntries(dropinformation[1], selectedNode);
						// if we have any entries left, i.e. not only double entries, add them now
						if (entries != null && entries.length() > 0) {
							// add new entry
							addEntries(entries, modifications, comment);
							// update toolbars
							// updateTreeView();
							updateToolbarAndMenu();
							return true;
						}
					} // here we have
						// - a bullet as drag-source
						// - and the root or a bullet (or: no entry) as drop-location
					else if (sourceinfo.length > 1 && sourceinfo[1].equals(Constants.DRAG_SOURCE_TYPE_BULLET)
							&& selectedNode.getAllowsChildren()) {
						// check for self-drop
						if (TreeUtil.getNodeTimestamp(movedNodeToRemove).equals(nodets)) {
							return false;
						}
						// cut bullet from XML-data file
						desktopObj.cutBulletToClip(dropinformation[dropinformation.length - 1]);
						// and paste the bullet at the target-destination
						desktopObj.pasteBulletFromClip(TreeUtil.getNodeTimestamp(selectedNode), selectedNode.isRoot());
						// update treeview and toolbars
						updateTreeView();
						updateToolbarAndMenu();
						return true;
					} // if we have no drag-information specified, check whether we have a table-drag
						// and can retrieve any entry-information
					else if (!selectedNode.isRoot()) {
						// try to extract entry-numbers from dropped string
						int[] entrynrs = Tools.retrieveEntryNumbersFromTransferHandler(str,
								dataObj.getCount(Daten.ZKNCOUNT));
						// if we have any entries left, i.e. not only double entries, add them now
						if (entrynrs != null && entrynrs.length > 0) {
							// create new string builder
							StringBuilder sb = new StringBuilder();
							// iterate all moved/copied/pasted entrynumbers
							for (int cnt = 0; cnt < entrynrs.length; cnt++) {
								// check whether entrynumber already exists
								if (!entryExists(entrynrs[cnt], selectedNode)) {
									// if not, add it.
									sb.append(entrynrs[cnt]).append(",");
								}
							}
							// delete last comma
							if (sb.length() > 1) {
								sb.setLength((sb.length() - 1));
								// add new entry
								addEntries(sb.toString());
								// update toolbars
								// updateTreeView();
								updateToolbarAndMenu();
								return true;
							}
						}
					}
				}
				return false;
			}

			@Override
			protected void cleanup(JComponent c, boolean remove) {
			}
		});
	}

	/**
	 * This method retrieves all entry-numbers of entries that have been dropped (or
	 * dragged and dropped) on the jTree. The method checks whether any of the
	 * dropped entries already exist as entry of the parent-bullet, and if so, the
	 * related entry-number will be removed.
	 *
	 * @param entries    the dropped entry-numbers as single string, comma
	 *                   separated.
	 * @param targetNode the node where the entries have been dropped
	 * @return a string with entry-numbers, comma separated, with double or multiple
	 *         entries of the {@code targetNode} (or its parent, if targetNode is no
	 *         bullet) removed.
	 */
	private String retrieveDropEntries(String entries, DefaultMutableTreeNode targetNode) {
		// split entries into array
		String[] singleentry = entries.split(",");
		// now we have to check whether the dragged entry already exists as sub-entry of
		// the target's bullet-point. therefore, we have to retrieve the closest
		// parent-bullet
		// to the drop-location
		DefaultMutableTreeNode parent = targetNode;
		// if the targetPath itself is not already a bullet, retrieve its parent.
		if (!targetNode.getAllowsChildren()) {
			parent = (DefaultMutableTreeNode) parent.getParent();
		}
		// check for null
		if (null == parent) {
			return null;
		}
		// go through all entries and check, whether they exists. if so, remove them
		// from the list,
		// so only valid entries are dropped...
		StringBuilder sb = new StringBuilder();
		for (String singleentry1 : singleentry) {
			if (!entryExists(Integer.parseInt(singleentry1), parent)) {
				sb.append(singleentry1).append(",");
			}
		}
		// delete last comma
		if (sb.length() > 1) {
			sb.setLength((sb.length() - 1));
		}
		// if all elements have been removed, return null
		if (sb.length() < 1) {
			return null;
		}
		// return result
		return sb.toString();
	}

	/**
	 * This method checks whether an entry with the number {@code dropnr} already
	 * exists as entry of the parent-bullet {@code parent}.
	 *
	 * @param dropnr the number of the dropped entry
	 * @param parent the parent-bullet of the dropped entry
	 * @return {@code true} if an entry with the same number as {@code dropnr}
	 *         already exists as entry of the parent-bullet {@code parent},
	 *         {@code false} otherwise.
	 */
	private boolean entryExists(int dropnr, DefaultMutableTreeNode parent) {
		// check for null
		if (null == parent) {
			return false;
		}
		// now go through all bullet's children
		for (int counter = 0; counter < parent.getChildCount(); counter++) {
			// get child
			DefaultMutableTreeNode doublechild = (DefaultMutableTreeNode) parent.getChildAt(counter);
			// retrieve the node's text and extract the entry-number
			int childnr = TreeUtil.extractEntryNumberFromNode(doublechild);
			// compare child's text with newBullet-text
			if (childnr == dropnr) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void windowOpened(WindowEvent e) {
	}

	@Override
	public void windowClosing(WindowEvent e) {
		closeWindow();
	}

	@Override
	public void windowClosed(WindowEvent e) {
	}

	@Override
	public void windowIconified(WindowEvent e) {
	}

	@Override
	public void windowDeiconified(WindowEvent e) {
	}

	@Override
	public void windowActivated(WindowEvent e) {
	}

	@Override
	public void windowDeactivated(WindowEvent e) {
	}

	/**
	 *
	 */
	private class MyCommentRenderer extends DefaultTreeCellRenderer {

		Icon commentIcon, luhmannIcon;
		boolean useMacBackgound;

		public MyCommentRenderer(Icon icon, Icon iconLuhmann, boolean bg) {
			commentIcon = icon;
			luhmannIcon = iconLuhmann;
			useMacBackgound = bg;
		}

		@Override
		public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
				boolean leaf, int row, boolean hasFocus) {

			super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
			setBackgroundNonSelectionColor(tree.getBackground());
			if (!leaf && !sel && useMacBackgound) {
				setForeground(ColorUtil.colorJTreeDarkText);
			}
			setFont(getFont().deriveFont((leaf) ? Font.PLAIN : Font.BOLD));
			if (isCommentNode(value)) {
				setIcon(commentIcon);
			} else if (isLuhmannNode(value)) {
				setIcon(luhmannIcon);
			}
			return this;
		}

		/**
		 * This method checks whether a selected node has a comment or not.
		 *
		 * @param value the selected node
		 * @return {@code true} if the selected node has a comment, {@code false}
		 *         otherwise.
		 */
		protected boolean isCommentNode(Object value) {
			// if no value return
			if (null == value) {
				return false;
			}
			// retrieve node
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
			// when root, return
			if (node.isRoot()) {
				return false;
			}
			return (!desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>").isEmpty());
		}

		/**
		 * This method checks whether an entry of a selected node has follower numbers
		 * or not.
		 *
		 * @param value the selected node
		 * @return {@code true} if the entry of the selected node has followers,
		 *         {@code false} otherwise.
		 */
		protected boolean isLuhmannNode(Object value) {
			// if no value return
			if (null == value || !settingsObj.getShowLuhmannIconInDesktop()) {
				return false;
			}
			// retrieve node
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
			// when root, return
			if (node.isRoot()) {
				return false;
			}
			// else, get entry number of selected node
			int entry = TreeUtil.extractEntryNumberFromNode(node);
			// no entry selected? then return false
			if (-1 == entry) {
				return false;
			}
			// return, whether entry has followers
			return (dataObj.hasLuhmannNumbers(entry));
		}
	}

	/**
	 * Updates/enables/disables the toolbar- and menu-buttons, depending on whether
	 * the functions are available and executable or not.
	 */
	private void updateToolbarAndMenu() {
		// get selection
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		// enable actions that require a selected bullet, but no root
		setBulletSelected((node != null) && (node.getAllowsChildren()));
		// enable actions that either require a selcted bullet or child-node, but no
		// root
		setNodeSelected((node != null) && (!node.isRoot()));
		// enable actions that either require a selcted bullet or child-node, but no
		// root
		setEntryNodeSelected((node != null) && (!node.isRoot()) && (!node.getAllowsChildren()));
		// enable actions that require any selection
		setAnyNodeSelected(node != null);
		setModifiedEntryNode(desktopObj.isModifiedEntry(getSelectedNodeTimestamp()));
		// enable paste-option
		setClipFilled(
				((clipBullet && isBulletSelected()) || (!clipBullet && clipEntries != null && clipEntries.length > 0)));
		// enable the move-actions, which let the user move an entry/bullet up and down
		setMoveUpEnabled(!isFirstNode() && node != null && !node.isRoot());
		setMoveDownEnabled(!isLastNode() && node != null && !node.isRoot());
		// create string that will hold the luhmann-numbers
		String luhmann = "";
		// get selected entry-number
		int nr = getSelectedEntryNumber();
		// if we have a valid entry, get luhmann-numbers
		if (nr != -1) {
			luhmann = dataObj.getSubEntriesCsv(nr);
		}
		// enable actions that require a selected child-node (entty), that has
		// luhmann-numbers
		setLuhmannNodeSelected(isNodeSelected() && !luhmann.isEmpty());
	}

	/**
	 * This method retrieves the entry of the selected node and extracts its
	 * entry-number.
	 *
	 * @return the number of the selected entry, or -1 if nothing was selected.
	 */
	private int getSelectedEntryNumber() {
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		// if we have a valid node, go on...
		if (node != null) {
			// return TreeUtil.extractEntryNumberFromNodeText(node);
			return TreeUtil.extractEntryNumberFromNode(node);
		}
		return -1;
	}

	/**
	 * This method updates the display, i.e. receiving the entry-structure from the
	 * jTree and displays all those entries in html-formatting in the jEditorPane.
	 */
	private synchronized void updateDisplay() {
		// when the display is up to date, do nothing here...
		if (!isNeedsUpdate()) {
			return;
		}
		// cancel already running task if necessary, so we don't have more parallel
		// tasks running
		if (cDisplayTask != null) {
			cDisplayTask.cancel(true);
		}
		// if task is already running, leave...
		if (cDisplayTaskIsRunning) {
			return;
		}
		Task<? extends Object, ? extends Void> cdT = displayTask();
		// get the application's context...
		ApplicationContext appC = Application.getInstance().getContext();
		// ...to get the TaskMonitor and TaskService
		TaskMonitor tM = appC.getTaskMonitor();
		TaskService tS = appC.getTaskService();
		// with these we can execute the task and bring it to the foreground
		// i.e. making the animated progressbar and busy icon visible
		tS.execute(cdT);
		tM.setForegroundTask(cdT);
	}

	/**
	 * This method fills recursively all entries' contents to the jEditorPane.
	 * Therefore, the jTreeDesktop is enumerated. Each element is then converted to
	 * a string, html-formatted, and appended to a StringBuilder. At the end, the
	 * StringBuilder's content is set to the jEditorPane.
	 *
	 * @param node the root node, as starting point for the jTree-enumeration
	 * @param sb   the stringbuilder which finally will contain all content in
	 *             html-format
	 */
	private void exportEntriesToEditorPane(DefaultMutableTreeNode node, StringBuilder sb, boolean showComments) {
		// get a list with all children of the node
		Enumeration<?> en = node.children();
		// go through all children
		while (en.hasMoreElements()) {
			// get the child
			node = (DefaultMutableTreeNode) en.nextElement();
			// if the child is a bullet...
			if (node.getAllowsChildren()) {
				// retrieve bullet-level
				int lvl = node.getLevel();
				String level = String.valueOf(lvl);
				// new table row
				sb.append("<tr>").append(lineseparator);
				// check whether comments should be displayed
				if (showComments) {
					// retieve and create comment
					String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>");
					// insert comment as table-data
					sb.append("<td valign=\"top\" class=\"comment\">").append(com).append("</td>")
							.append(lineseparator);
				}
				// insert entry content
				sb.append("<td>").append("<h").append(level).append(">");
				// now create the reference-ankh, so we can use the "scrollToReference" method
				// of the jEditorPane easily each time the user clicks on an entry in the jTree
				// to scroll to that entry in the text field.
				sb.append("<a name=\"").append("entry").append(TreeUtil.getNodeTimestamp(node)).append("\">&nbsp;</a>");
				// append a new headline with the bullet's name
				sb.append(TreeUtil.getNodeText(node));
				// also add headline to wordcounter
				sbWordCountDisplayTask.append(TreeUtil.getNodeText(node)).append(" ");
				sb.append("</h").append(level).append(">").append("</td>").append("</tr>").append(lineseparator);
			} // now we know we have an entry. so get the entry number...
			else {
				// we now want to check whether the user has made modifications to the entry's
				// content, which are only made to the desktop (the content of the entry in the
				// main database
				// is not changed, so you can edit the desktop-entry without changing the
				// entry's original
				// content - this is useful when you want to add some words/phrases between
				// entries etc., which
				// should be applied only to the final text on the desktop, but not to the
				// original entries).
				//
				// in case we have modified an entry on the desktop, this entry has a "content"
				// element. to
				// retrieve the correct entry, we need to look for the unique timestamp of that
				// entry - since
				// an entry could appear multiple times on the desktop, thus the entry number
				// itself is no
				// valid value for retrieving the right entry. Therefore, each treenode has a
				// user-object
				// assigned, which holds the unique timestamp
				String text = desktopObj.retrieveModifiedEntryContentFromTimestamp(TreeUtil.getNodeTimestamp(node));
				// retrieve entry-number
				int nr = TreeUtil.extractEntryNumberFromNode(node);
				// if nothing found, retrieve regular entry
				// that means, if the entry with the unique-timestamp has no or an empty
				// content-element, the
				// entry was not modified - thus we retrieve the "original" entry.
				if (null == text || text.isEmpty()) {
					// also cleaned text for wordcounter
					sbWordCountDisplayTask.append(dataObj.getCleanZettelContent(nr)).append(" ");
					// get zettel-text
					text = HtmlUbbUtil.getHtmlContentForDesktop(dataObj, bibtexObj, settingsObj, nr, isHeadingVisible,
							isEntryNumberVisible, false, false);
				} // else if we have a modified entry-content, we still need to convert its
					// ubb-tags to HTML. this is done here...
				else {
					// also cleaned text for wordcounter
					sbWordCountDisplayTask.append(Tools.removeUbbFromString(text, true)).append(" ");
					// get the html-text for an entry which content is passed as parameter...
					text = HtmlUbbUtil.getHtmlContentForDesktop(dataObj, bibtexObj, settingsObj, text, nr,
							isHeadingVisible, isEntryNumberVisible, false, false);
				}
				// new table row
				sb.append("<tr>").append(lineseparator);
				// check whether comments should be displayed
				if (showComments) {
					// retieve and create comment
					String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>");
					// insert comment as table-data
					sb.append("<td valign=\"top\" class=\"comment\">").append(com).append("</td>");
				}
				sb.append("<td class=\"content\">").append(lineseparator);
				// now create the reference-ankh, so we can use the "scrollToReference" method
				// of the jEditorPane easily each time the user clicks on an entry in the jTree
				// to scroll to that entry in the text field.
				sb.append("<a name=\"").append("entry").append(TreeUtil.getNodeTimestamp(node)).append("\">&nbsp;</a>")
						.append(lineseparator);
				// and append the html-text of the entry...
				sb.append(text).append("</td>").append("</tr>").append(lineseparator);
			}
			// when the new node also has children, call this method again,
			// so we go through the strucuture recursively...
			if (node.getChildCount() > 0) {
				exportEntriesToEditorPane(node, sb, showComments);
			}
		}
	}

	/**
	 * This method fills recursively all entries' contents to the jEditorPane.
	 * Therefore, the jTreeDesktop is enumerated. Each element is then converted to
	 * a string, html-formatted, and appended to a StringBuilder. At the end, the
	 * StringBuilder's content is set to the jEditorPane.
	 *
	 * @param node the root node, as starting point for the jTree-enumeration
	 * @param sb   the stringbuilder which finally will contain all content in
	 *             html-format
	 */
	private void exportCommentsToEditorPane(DefaultMutableTreeNode node, StringBuilder sb) {
		// get a list with all children of the node
		Enumeration<?> en = node.children();
		// go through all children
		while (en.hasMoreElements()) {
			// get the child
			node = (DefaultMutableTreeNode) en.nextElement();
			// if the child is a bullet...
			if (node.getAllowsChildren()) {
				// retrieve bullet-level
				int lvl = node.getLevel();
				String level = String.valueOf(lvl);
				// retieve and create comment
				String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>");
				// check whether comment is empty or not
				if (com != null && !com.isEmpty()) {
					// new table row
					sb.append("<tr>");
					// insert paragraph heading
					sb.append("<td><h").append(level).append(">");
					// now create the reference-ankh, so we can use the "scrollToReference" method
					// of the jEditorPane easily each time the user clicks on an entry in the jTree
					// to scroll to that entry in the text field.
					sb.append("<a name=\"");
					sb.append("entry").append(TreeUtil.getNodeTimestamp(node));
					sb.append("\">&nbsp;</a>");
					// append a new headline with the bullet's name
					sb.append(TreeUtil.getNodeText(node));
					sb.append("</h").append(level).append(">");
					// insert comment as table-data
					sb.append("<p>").append(com).append("</p>");
					sb.append("</td></tr>").append(lineseparator);
					// also add headline and comment to wordcounter
					sbWordCountDisplayTask.append(TreeUtil.getNodeText(node)).append(" ").append(com).append(" ");
				}
			} // now we know we have an entry. so get the entry number...
			else {
				// retieve and create comment
				String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), "<br>");
				// check whether comment is empty or not
				if (com != null && !com.isEmpty()) {
					// new table row
					sb.append("<tr>");
					sb.append("<td class=\"content\">");
					// now create the reference-ankh, so we can use the "scrollToReference" method
					// of the jEditorPane easily each time the user clicks on an entry in the jTree
					// to scroll to that entry in the text field.
					sb.append("<a name=\"");
					sb.append("entry").append(TreeUtil.getNodeTimestamp(node));
					sb.append("\">&nbsp;</a>");
					// and append the html-text of the entry...
					sb.append(HtmlUbbUtil.getZettelTitleForDesktop(dataObj, TreeUtil.extractEntryNumberFromNode(node),
							isEntryNumberVisible));
					// insert comment as table-data
					sb.append("<p>").append(com).append("</p>");
					sb.append("</td></tr>").append(lineseparator);
					// also cleaned text for wordcounter
					sbWordCountDisplayTask.append(com).append(" ");
				}
			}
			// when the new node also has children, call this method again,
			// so we go through the strucuture recursively...
			if (node.getChildCount() > 0) {
				exportCommentsToEditorPane(node, sb);
			}
		}
	}

	/**
	 * This method scrolls to that entry in the jEditorPane, that is selected from
	 * the jTree. This is achieved by simply activating a hyperlink (ankh), thus we
	 * can scroll to the reference.<br>
	 * <br>
	 * A unique reference for each entry is set in the node's text in the jTree via
	 * the method
	 * {@link #fillChildren(org.jdom.Element, javax.swing.tree.DefaultMutableTreeNode, javax.swing.tree.DefaultTreeModel)
	 * fillChildren} and
	 * {@link #exportEntriesToEditorPane(javax.swing.tree.DefaultMutableTreeNode, java.lang.StringBuilder)
	 * exportEntriesToEditorPane}.
	 */
	private void scrollToEntry() {
		// get selected node
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		if (null == node || node.isRoot()) {
			return;
		}
		// get the node's text. this is what we want to search in the editor pane
		jEditorPaneMain.scrollToReference("entry" + getSelectedNodeTimestamp());
	}

	@Action
	public void findLive() {
		// first, update the display, so we search in the current desktop
		updateDisplay();
		// display the panel that contains the textfield for the search terms
		// and the find next/prev-buttons
		jPanelLiveSearch.setVisible(true);
		// set input-focus to textfield
		jTextFieldLiveSearch.requestFocusInWindow();

	}

	@Action
	public void findLiveNext() {
		// first, we have to create a string that equals the ankh (reference) where
		// the editorpane should scroll to. each found search term has a link-tag with
		// a consecutive numbering (<a name="hl1">, <a name="hl2"> etc...)
		// the variable "findlivepos" contains the number of the current references ankh
		String ankh = "hl" + findlivepos;
		// scroll the the reference
		jEditorPaneMain.scrollToReference(ankh);
		// increase findlivepos to refer to the next reference
		if (findlivepos < findlivemax) {
			findlivepos++;
		} // if we reach the last reference, start at first reference again
		else {
			findlivepos = 1;
		}
	}

	@Action
	public void findLivePrev() {
		// decrease findlivepos.
		if (findlivepos > 1) {
			findlivepos--;
		} // when we reached the first reference, set to last occurencs of search terms
		else {
			findlivepos = findlivemax;
		}
		// create reference string
		String ankh = "hl" + findlivepos;
		// and scroll to reference
		jEditorPaneMain.scrollToReference(ankh);
	}

	@Action
	public void findCancel() {
		// restore complete page without highlighting
		jEditorPaneMain.setText(HtmlUbbUtil.getHtmlHeaderForDesktop(settingsObj, false) + completePage);
		// scroll to top
		jEditorPaneMain.setCaretPosition(0);
		// hide live-search-bar
		jPanelLiveSearch.setVisible(false);
	}

	private void updateLiveSearchDisplay() {
		// retrieve search term from textfield and set it as highlight-term for
		// the html-conversion
		HtmlUbbUtil.setHighlighTerms(new String[] { jTextFieldLiveSearch.getText() },
				HtmlUbbUtil.HIGHLIGHT_STYLE_LIVESEARCH, false);
		// init the counter for the references to the found search terms
		findlivepos = 1;
		// retrieve the desktop-content with highlighted search term
		StringBuilder newtext = new StringBuilder(
				HtmlUbbUtil.highlightSearchTerms(completePage, HtmlUbbUtil.HIGHLIGHT_STYLE_LIVESEARCH));
		// counter for bulding the HTML-link-tags, so we can scroll directly to each
		// references
		// found search term, using the editor pane's scrollToReference()-method
		int counter = 1;
		int pos = 0;
		// while we find a highlighted search term, we want to insert an ankh
		// (html-link-tag
		// including the reference-name) before that search term
		while (pos != -1) {
			// find occurence of highlighted text
			pos = newtext.toString().indexOf("<span class=\"hs_ls\"", pos);
			// if we found something...
			if (pos != -1) {
				// insert linktag before.
				newtext.insert(pos, "<a name=\"hl" + counter++ + "\"></a>");
				// and increase position-index, so we don't have an infinite loop that always
				// finds
				// the same <span>-tag
				pos = pos + 40;
			}
		}
		// store the maximum amount of found/highlighted search terms, so we know when
		// to
		// restart with our reference counter. see findLiveNext() and findLivePrev() for
		// more details
		findlivemax = counter - 1;
		// set new highlighted text to editor pane
		jEditorPaneMain.setText(HtmlUbbUtil.getHtmlHeaderForDesktop(settingsObj, false) + newtext.toString());
		// set scroll-area to top
		jEditorPaneMain.setCaretPosition(0);
		// and scroll to first reference in the editor pane
		String ankh = "hl1";
		jEditorPaneMain.scrollToReference(ankh);
	}

	@Action
	public void switchHeadingsVisibility() {
		isHeadingVisible = !isHeadingVisible;
		headingsVisibleMenuItem.setSelected(isHeadingVisible);
		setNeedsUpdate(true);
	}

	@Action
	public void switchLuhmannVisibility() {
		isLuhmannIconVisible = !isLuhmannIconVisible;
		luhmannIconVisible.setSelected(isLuhmannIconVisible);
		settingsObj.setShowLuhmannIconInDesktop(isLuhmannIconVisible);
		updateTreeView();
	}

	@Action
	public void switchEntryNumberVisibility() {
		isEntryNumberVisible = !isEntryNumberVisible;
		entryNumberVisibleMenuItem.setSelected(isEntryNumberVisible);
		setNeedsUpdate(true);
	}

	@Action
	public void menuDisplayDesktopWithComments() {
		settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITH_COMMENTS);
		setNeedsUpdate(true);
	}

	@Action
	public void menuDisplayDesktopWithoutComments() {
		settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITHOUT_COMMENTS);
		setNeedsUpdate(true);
	}

	@Action
	public void menuDisplayDesktopOnlyComments() {
		settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_ONLY_COMMENTS);
		setNeedsUpdate(true);
	}

	/**
	 * This method is called whenever an entry that is also on the desktop was
	 * changed. In this case we assume that the entry's content was changed, so we
	 * need an update to the treeview (in case the entry has a new title, we need to
	 * display it in the treeview as well) and we need an update to the
	 * html-content.
	 */
	public void updateEntriesAfterEditing() {
		updateTreeView();
	}

	/**
	 * This method updates the treeview after each change made to the desktop. The
	 * changes are only applied to the desktop-data-file (the xml-file managed in
	 * the {@link #desktopObj CDesktop-Class}). This method retrieves the structure
	 * from this xml-document and copies it to the treeview.<br>
	 * <br>
	 * Updating the treeview does <b>not</b> update the display of the entries as
	 * well, since many display-updates take much time. Rather the action
	 * {@link #updateView() updateView} is enabled, which updates the display.
	 */
	private void updateTreeView() {
		// get the treemodel
		DefaultTreeModel dtm = (DefaultTreeModel) jTreeDesktop.getModel();
		// and first of all, clear the jTree
		dtm.setRoot(null);
		// create a new root element from the current desktop name and set it as root
		DefaultMutableTreeNode root = new DefaultMutableTreeNode(new TreeUserObject(
				desktopObj.getDesktopName(jComboBoxDesktop.getSelectedIndex()), Constants.ROOT_ID_NAME, ""));
		dtm.setRoot(root);
		// get current desktop-element
		Element d = desktopObj.getCurrentDesktopElement();
		// check whether the current desktop has any children at all
		if (desktopObj.hasChildren(d)) {
			// create treeview-content
			fillChildren(d, root, dtm);
		}
		// finally, expand the whole tree
//        expandAllTrees(true, jTreeDesktop);
		expandAllTrees();
		// check whether a certain entry should be selected or not
		if (displayentrynr != -1) {
			// check whether entry exists in current desktop
			if (desktopObj.isEntryInCurrentDesktop(displayentrynr)) {
				// if yes, retrieve element
				Element en = desktopObj.getFoundDesktopElement();
				// check for valid value
				if (en != null) {
					// get timestamp of entry
					String timestamp = en.getAttributeValue("timestamp");
					// select entry in treeview
					selectTreePath(timestamp);
				}
			}
			// reset display entry nr
			displayentrynr = -1;
		}
		// display needs to be updated...
		setNeedsUpdate(true);
	}

	/**
	 * This method updates the jTreeView. Each time an update for the treevuew is
	 * needed, this method is called. It then recursevly traverses all XML-Elements
	 * of the currently activated desktop-element, where the starting
	 * desktop-element is passed in the parameter {@code e}. <br>
	 * <br>
	 * The method retrieves each element, checks whether the element is an entry- or
	 * a bullet-element, than either, in case of a bullet point, uses the
	 * name-attribute as node-name and appends the timestamp-attribute as ID; or it
	 * retrieves the entry's title from the entry-number that is stored in each
	 * entry-element, and appends the entry's timestamp-attribute as ID. <br>
	 * <br>
	 * After that, the node is inserted in the jTree.
	 *
	 * @param e
	 * @param n
	 * @param dtm
	 */
	private void fillChildren(Element e, DefaultMutableTreeNode n, DefaultTreeModel dtm) {
		// get a list with all children of the element
		List<Element> children = e.getChildren();
		// create an iterator
		Iterator<Element> it = children.iterator();
		// go through all children
		while (it.hasNext()) {
			// get the child
			e = it.next();
			// create a new node
			DefaultMutableTreeNode node;
			// we have to ignore the comment-tags here. comments are no tags that will
			// be displayed in the jtree, but that store comments which will be displayed
			// in the jeditorpane (see "updateDisplay" method for further details)
			if (!e.getName().equals("comment")) {
				// if the child is a bullet...
				if (e.getName().equals("bullet")) {
					// create new stringbuilder
					StringBuilder sb = new StringBuilder();
					// append name of bullet point
					sb.append(e.getAttributeValue("name"));
//                    // and append unique id, which is the element's timestamp
//                    sb.append(" [id#").append(e.getAttributeValue("timestamp")).append("]");
//                    // create a node with the element's name-attribute
//                    node = new DefaultMutableTreeNode(sb.toString());
					// create a node with the element's name-attribute
					node = new DefaultMutableTreeNode(
							new TreeUserObject(sb.toString(), e.getAttributeValue("timestamp"), ""));
					// and tell node to have children
					node.setAllowsChildren(true);
				} else {
					// now we know we have an entry. so get the entry number...
					int nr = Integer.parseInt(e.getAttributeValue("id"));
					// get the zettel title
					String title = TreeUtil.getEntryDisplayText(dataObj, settingsObj.getShowDesktopEntryNumber(),
							new EntryID(nr));
					// create a new node
					node = new DefaultMutableTreeNode(
							new TreeUserObject(title, e.getAttributeValue("timestamp"), String.valueOf(nr)));
					// and tell node not to have children
					node.setAllowsChildren(false);
				}
				// add new node to treeview
				dtm.insertNodeInto(node, n, n.getChildCount());
				// when the new element also has children, call this method again,
				// so we go through the strucuture recursively...
				if (desktopObj.hasChildren(e)) {
					fillChildren(e, node, dtm);
				}
			}
		}
	}

	/**
	 * This method retrieves all entries on the desktop and adds their number to the
	 * list {@code liste}. This array of entry-numbers is needed in the
	 * export-dialog.
	 *
	 * @param e     the starting point for the jTree-enumeration, either the root
	 *              elementor a bullet (if only a bullet should be exported, see
	 *              {@link #exportDesktopBullet() exportDesktopBullet()}).
	 * @param liste an array-object that will hold the found entry-nubers
	 */
	private void createExportEntries(Element e, ArrayList<Object> liste) {
		// if we have no element, return.
		if (null == e) {
			return;
		}
		// get a list with all children of the element
		List<Element> children = e.getChildren();
		// create an iterator
		Iterator<Element> it = children.iterator();
		// go through all children
		while (it.hasNext()) {
			// get the child
			e = it.next();
			// we have to ignore the comment-tags here. comments are no tags that will
			// be displayed in the jtree, but that store comments which will be displayed
			// in the jeditorpane (see "updateDisplay" method for further details)
			if (!e.getName().equals("comment")) {
				// if the child is a bullet...
				if (e.getName().equals("bullet")) {
					// first, we want to retrieve the header-level
					int headerlevel = 1;
					// get bullet's parent
					Element f = e.getParentElement();
					// as long as we have not reached the root, get further parent-elements
					// and increase counter for header-level
					while (!f.isRootElement()) {
						f = f.getParentElement();
						headerlevel++;
					}
					// add the element's name-attribute. since headers might consist of only
					// numbers,
					// we add a char here. this is necessary, since the export-methods distinguish
					// between headers and entry-numbers simply by parsing integer-values. if the
					// parsing
					// succeeds, we have an entry, if a NumberFormatException is thrown, we have a
					// headline.
					// to treat headline with numbers only as headlines, we add a char to be sure
					// that every
					// headline will throw an exception when parsing the array's elements to
					// integer.
					liste.add("h" + headerlevel + e.getAttributeValue("name"));
				} else {
					// now we know we have an entry. so get the entry number...
					int nr = Integer.parseInt(e.getAttributeValue("id"));
					liste.add(nr);
				}
				// when the new element also has children, call this method again,
				// so we go through the strucuture recursively...
				if (desktopObj.hasChildren(e)) {
					createExportEntries(e, liste);
				}
			}
		}
	}

//    /**
//     * If expand is true, expands all nodes in the tree.
//     * Otherwise, collapses all nodes in the tree.
//     */
//    public void expandAllTrees(boolean expand, JTree tree) {
//        // get tree-root
//        TreeNode root = (TreeNode)tree.getModel().getRoot();
//        // Traverse tree from root
//        expandAllTrees(new TreePath(root), expand, tree);
//    }
//    private void expandAllTrees(TreePath parent, boolean expand, JTree tree) {
//        // Traverse children
//        TreeNode node = (TreeNode)parent.getLastPathComponent();
//        // if we have children, go on
//        if (node.getChildCount() >= 0) {
//            // itereate all children
//            for (Enumeration e=node.children(); e.hasMoreElements();) {
//                TreeNode n = (TreeNode)e.nextElement();
//                TreePath path = parent.pathByAddingChild(n);
//                expandAllTrees(path, expand, tree);
//            }
//        }
//        // Expansion or collapse must be done bottom-up
//        if (expand) {
//            tree.expandPath(parent);
//        } else {
//            tree.collapsePath(parent);
//        }
//    }
	/**
	 * If expand is true, expands all nodes in the tree. Otherwise, collapses all
	 * nodes in the tree.
	 */
	public void expandAllTrees() {
		// get tree-root
		TreeNode root = (TreeNode) jTreeDesktop.getModel().getRoot();
		// Traverse tree from root
		expandAllTrees(new TreePath(root));
	}

	private void expandAllTrees(TreePath parent) {
		// Traverse children
		TreeNode node = (TreeNode) parent.getLastPathComponent();
		// if we have children, go on
		if (node.getChildCount() >= 0) {
			// itereate all children
			for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
				DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
				TreePath path = parent.pathByAddingChild(n);
				if (n.getAllowsChildren()) {
					// Expansion or collapse must be done bottom-up
					if (desktopObj.isBulletTreefoldExpanded(TreeUtil.getNodeTimestamp(n))) {
						jTreeDesktop.expandPath(path);
						expandAllTrees(path);
					} else {
						jTreeDesktop.collapsePath(path);
					}
				}
			}
		}
//        if (node.getAllowsChildren()) {
//            // Expansion or collapse must be done bottom-up
//            if (desktopObj.isBulletTreefoldExpanded(CCommonMethods.getNodeTimestamp((DefaultMutableTreeNode)node))) {
//                jTreeDesktop.expandPath(parent);
//            } else {
//                jTreeDesktop.collapsePath(parent);
//            }
//        }
	}

	/**
	 * This method adds a new desktop to the desktop-data-file. The user can input a
	 * new description (string-value). After that, the string is passed to the
	 * CDesktopData-class'es method "addNewDesktop", where a new desktop-element is
	 * created
	 */
	@Action
	public void newDesktop() {
		// user-input for new desktop-description
		String newDesk = JOptionPane.showInputDialog(null, resourceMap.getString("newDesktopMsg"),
				resourceMap.getString("newDesktopTitle"), JOptionPane.PLAIN_MESSAGE);
		// if we have any valdi input, go on...
		if ((newDesk != null) && (newDesk.length() > 0)) {
			// add the description as new element to the desktop-data-class
			if (desktopObj.addNewDesktop(newDesk)) {
				// save current notes
				desktopObj.setDesktopNotes(1, jTextArea1.getText());
				desktopObj.setDesktopNotes(2, jTextArea2.getText());
				desktopObj.setDesktopNotes(3, jTextArea3.getText());
				// get the treemodel
				DefaultTreeModel dtm = (DefaultTreeModel) jTreeDesktop.getModel();
				// set the desktop-description as root-element.
				DefaultMutableTreeNode root = new DefaultMutableTreeNode(newDesk);
				root.setAllowsChildren(true);
				dtm.setRoot(root);
				// and update combo box
				updateComboBox(false);
			} else {
				// desktop-name already existed, so desktop was not added...
				JOptionPane.showMessageDialog(this, resourceMap.getString("errDesktopExistsMsg"),
						resourceMap.getString("errDesktopExistsTitle"), JOptionPane.PLAIN_MESSAGE);
			}
		} // if new desktop action was cancelled, check whether we have any desktops at
			// all...
		else if (desktopObj.getCount() < 1) {
			// if not, close window
			resetAndClose();
		}
	}

	/**
	 * This action renames a bullet point, including the root-bullet, i.e. the name
	 * of the desktop. Entry-nodes cannot be renamed.
	 */
	@Action(enabledProperty = "bulletSelected")
	public void renameBullet() {
		// copy bullet's name into variable
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		// open an input-dialog, setting the selected value as default-value
		String newBulletName = (String) JOptionPane.showInputDialog(this, resourceMap.getString("editBulletMsg"),
				resourceMap.getString("editBulletTitle"), JOptionPane.PLAIN_MESSAGE, null, null, node.toString());
		// if we have a valid return-value, and this bulletname does not already
		// exist...
		if ((newBulletName != null) && (newBulletName.length() > 0) && (!checkIfBulletExists(newBulletName))) {
			// ...either change desktop's name if the root is selected
			if (node.isRoot()) {
				// check whether renaming succeeded
				if (!desktopObj.setDesktopName(desktopObj.getCurrentDesktopNr(), newBulletName)) {
					// if not, tell user...
					JOptionPane.showMessageDialog(this, resourceMap.getString("errRenameDesktopMsg"),
							resourceMap.getString("errRenameDesktopTitle"), JOptionPane.PLAIN_MESSAGE);
					return;
				}
				// update the combobox
				updateComboBox(false);
			} // ...or change the name of the selected bullet
			else {
				if (!desktopObj.renameBullet(TreeUtil.getNodeTimestamp(node), newBulletName)) {
					// if not, tell user...
					JOptionPane.showMessageDialog(this, resourceMap.getString("errRenameBulletMsg"),
							resourceMap.getString("errRenameBulletTitle"), JOptionPane.PLAIN_MESSAGE);
					return;
				}
				// update treeview
				updateTreeView();
			}
		}
	}

	/**
	 * This method deletes the selected entry, bullet with child-entries or even the
	 * complete desktop if the root is selected.
	 */
	@Action(enabledProperty = "anyNodeSelected")
	public void deleteNode() {
		// get selection
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		// if we have a valid selection, go on
		if (node != null) {
			// variable that indicates what type of node we have to delete
			int delete_what;
			// check what we have to delete
			if (node.isRoot()) {
				delete_what = Constants.DEL_DESKTOP;
			} else if (node.getAllowsChildren()) {
				delete_what = Constants.DEL_BULLET;
			} else {
				delete_what = Constants.DEL_ENTRY;
			}
			// create empty string
			String msg = "";
			// create message for confirm dialog, based on the type what we want to delete
			switch (delete_what) {
			case Constants.DEL_DESKTOP:
				msg = resourceMap.getString("askForDeleteDesktopMsg");
				break;
			case Constants.DEL_BULLET:
				msg = resourceMap.getString("askForDeleteBulletMsg");
				break;
			}
			int option = -1;
			// ask for delete only when the root or a bullet has to be deleted
			if (delete_what != Constants.DEL_ENTRY) {
				// ask user whether the node should be deleted
				option = JOptionPane.showConfirmDialog(null, msg, resourceMap.getString("askForDeleteTitle"),
						JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);
			}
			// if yes, go on
			if ((JOptionPane.YES_OPTION == option) || (Constants.DEL_ENTRY == delete_what)) {
				// check which type of node was selected. either root, bullet or entry; and
				// delete the related entry/bullet with children/complete desktop
				switch (delete_what) {
				case Constants.DEL_DESKTOP:
					// delete desktop
					desktopObj.deleteDesktop();
					// if we have any desktops left, update treeview
					if (desktopObj.getCount() > 0) {
						updateComboBox(false);
					} // else reset all fields and close window
					else {
						resetAndClose();
					}
					break;

				case Constants.DEL_BULLET:
					// delete parent
					desktopObj.deleteBullet(TreeUtil.getNodeTimestamp(node));
					// update view
					updateTreeView();
					break;

				case Constants.DEL_ENTRY:
					// delete entry
					desktopObj.deleteEntry(TreeUtil.getNodeTimestamp(node));
					// update view
					updateTreeView();
					break;
				}
			}
		}
	}

	private void resetAndClose() {
		// set click to update-text
		jEditorPaneMain.setText(resourceMap.getString("clickToUpdateText"));
		// reset tree
		initTree();
		// reset combobox
		updateComboBox(true);
		// check whether memory usage is logged. if so, tell logger that new entry
		// windows was opened
		if (settingsObj.isMemoryUsageLogged) {
			// log info
			Constants.zknlogger.log(Level.INFO, "Memory usage logged. Desktop Window closed.");
		}
		// make window invisible
		setVisible(false);
	}

	/**
	 * Opens a dialog where the user can choose which additional items for an entry
	 * (like author, remarks etc.) should be displayed in the desktop.
	 */
	@Action
	public void displayItems() {
		if (null == desktopDisplayItemsDlg) {
			// create a new dialog with the desktop-dialog, passing some initial values
			desktopDisplayItemsDlg = new CDesktopDisplayItems(this, settingsObj);
			// center window
			desktopDisplayItemsDlg.setLocationRelativeTo(this);
		}
		// show window
		ZettelkastenApp.getApplication().show(desktopDisplayItemsDlg);
		// when the user made changes and applies them...
		if (desktopDisplayItemsDlg.isNeedsUpdate()) {
			// tell programm that we need an update to the display.
			setNeedsUpdate(true);
		}
		// delete the windows
		desktopDisplayItemsDlg.dispose();
		desktopDisplayItemsDlg = null;
	}

	/**
	 * This method adds a new header/bulletpoint to the desktop (and to the jtree).
	 * Bullets differ from "usual" note in such case, that they are allowed to have
	 * children - in contrary to nodes that refer to entries, which may not have
	 * children. <br>
	 * <br>
	 * New bullet are always addes to the end of a selected node's children-list,
	 * while a new "entry-node" should be added <b>before</b> bullets. Thus, in a
	 * children list, first come all entry-nodes, than all bullet-nodes (always in
	 * this order).
	 */
	@Action(enabledProperty = "bulletSelected")
	public void addBullet() {
		// wait for user input
		String newBullet = JOptionPane.showInputDialog(null, resourceMap.getString("newBulletMsg"),
				resourceMap.getString("newBulletTitle"), JOptionPane.PLAIN_MESSAGE);
		// if we have a valid input and no cancel-operation, go on
		if (newBullet != null && newBullet.length() > 0) {
			// now we have to check whether the name of "newBullet" already exists as a
			// bullet on this
			// level of the outline/structure. Therefor, check whether "insert" is a
			// selected entry or a node.
			// if it's an entry, thus the new bullet is located on the same level, retrieve
			// the parent.
			// then we go through all parent's children and check for the occurence of a
			// bullet named
			// "newBullet".
			if (checkIfBulletExists(newBullet)) {
				return;
			}
			// retrieve selected node
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
			// add bullet to xml-file. therefor, check whether selection is the root, then
			// pass
			// "null" as parameter. in every other case, pass the bullet's timestamp as
			// parameter
			String timestamp = desktopObj.addBullet((node.isRoot()) ? null : TreeUtil.getNodeTimestamp(node),
					newBullet);
			// update treeview
			updateTreeView();
			// add new bullet to path and re-select new path...
			selectTreePath(timestamp);
			// update the menus/toolbar
			updateToolbarAndMenu();
		}
	}

	/**
	 * This method checks whether a new bullet {@code newBullet}, that should be
	 * added/inserted as sub-bullet to an existing bullet {@code insert}, already
	 * exists as sub-element of the parent {@code insert} or not.
	 *
	 * @param newBullet the name of the new bullet that should be inserted as child
	 *                  of {@code insert}
	 * @param insert    the parent-bullet, where the bullet {@code newBullet} should
	 *                  be added to
	 * @return {@code true} if a bullet which name equals {@code newBullet} already
	 *         exists, false if {@code newBullet} does not exist and can
	 *         successfully be added/inserted.
	 */
	private boolean checkIfBulletExists(String newBullet) {
		// get the selected node, so we know where to insert the new bullet
		DefaultMutableTreeNode insert = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		// now we have to check whether the name of "newBullet" already exists as a
		// bullet on this
		// level of the outline/structure. Therefor, check whether "insert" is a
		// selected entry or a node.
		// if it's an entry, thus the new bullet is located on the same level, retrieve
		// the parent.
		// then we go through all parent's children and check for the occurence of a
		// bullet named
		// "newBullet".
		DefaultMutableTreeNode parent = ((insert.getAllowsChildren()) ? insert
				: (DefaultMutableTreeNode) insert.getParent());
		// got through all parent's children
		for (int cnt = 0; cnt < parent.getChildCount(); cnt++) {
			// get child
			DefaultMutableTreeNode child = (DefaultMutableTreeNode) parent.getChildAt(cnt);
			// since each bullet-point has a timestamp-id, we need to extract the bullet's
			// name
			// only for comparison
			String text = child.toString();
			int pos = text.indexOf("[");
			// only continue if we found something...
			if (pos != -1) {
				// compare child's text with newBullet-text
				if (newBullet.equalsIgnoreCase(text.substring(0, pos).trim())) {
					// if we found a match, tell user about cancelling
					JOptionPane.showMessageDialog(this, resourceMap.getString("errBulletExistsMsg"),
							resourceMap.getString("errBulletExistsTitle"), JOptionPane.PLAIN_MESSAGE);
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * This methods adds a new entry-node, i.e. a node that is not allowed to have
	 * children, to the jTree. <br>
	 * <br>
	 * First of all, an input-dialog is opened where the user can enter several
	 * entry-numbers, separated by commas, including "from-to"-option (e.g.:
	 * "4,7,13-16,22"). Then each entry is retrieved, setting entry-number and
	 * entry-title as node-text. <br>
	 * <br>
	 * The nodes are added to the end of the selected node's children-list, but
	 * <b>before</b> the first heading/bullet. so, a child-list always lists first
	 * the entry-nodes (that are not allowed to have children), followed by
	 * header/bullet-nodes (that may have children). <br>
	 * <br>
	 * An entry-node shall never be located <b>behind</b> a bullet/header node! <br>
	 * <br>
	 * <i>This method is separated in two parts!</i> The main part can be found in
	 * the {@link #addEntries addEntries} method.
	 */
	@Action(enabledProperty = "nodeSelected")
	public void addEntry() {
		// wait for user input
		String newEntries = JOptionPane.showInputDialog(null, resourceMap.getString("newEntryMsg"),
				resourceMap.getString("newEntryTitle"), JOptionPane.PLAIN_MESSAGE);
		// if we have a valid input and no cancel-operation, go on
		if (newEntries != null && newEntries.length() > 0) {
			addEntries(newEntries);
		}
	}

	@Action(enabledProperty = "entryNodeSelected")
	public void editEntry() {
		int nr = getSelectedEntryNumber();
		if (nr != -1) {
			zknframe.openEditWindow(true, nr, false, false, -1);
		}
	}

	@Action(enabledProperty = "nodeSelected")
	public void insertEntry() {
		zknframe.editEntryFromDesktop = true;
		zknframe.openEditWindow(false, -1, false, false, getSelectedEntryNumber());
	}

	/**
	 * This methods adds a new entry-node, i.e. a node that is not allowed to have
	 * children, to the jTree. <br>
	 * <br>
	 * First of all, an input-dialog is opened where the user can enter several
	 * entry-numbers, separated by commas, including "from-to"-option (e.g.:
	 * "4,7,13-16,22"). Then each entry is retrieved, setting entry-number and
	 * entry-title as node-text. <br>
	 * <br>
	 * The nodes are added to the end of the selected node's children-list, but
	 * <b>before</b> the first heading/bullet. so, a child-list always lists first
	 * the entry-nodes (that are not allowed to have children), followed by
	 * header/bullet-nodes (that may have children). <br>
	 * <br>
	 * An entry-node shall never be located <b>behind</b> a bullet/header node! <br>
	 * <br>
	 * <i>This method is separated in two parts!</i> The inital part can be found in
	 * the {@link #addEntry addEntry} method.
	 *
	 * @param newEntries
	 */
	private void addEntries(String newEntries) {
		addEntries(newEntries, null, null);
	}

	/**
	 * This methods adds a new entry-node, i.e. a node that is not allowed to have
	 * children, to the jTree. <br>
	 * <br>
	 * First of all, an input-dialog is opened where the user can enter several
	 * entry-numbers, separated by commas, including "from-to"-option (e.g.:
	 * "4,7,13-16,22"). Then each entry is retrieved, setting entry-number and
	 * entry-title as node-text. <br>
	 * <br>
	 * The nodes are added to the end of the selected node's children-list, but
	 * <b>before</b> the first heading/bullet. so, a child-list always lists first
	 * the entry-nodes (that are not allowed to have children), followed by
	 * header/bullet-nodes (that may have children). <br>
	 * <br>
	 * An entry-node shall never be located <b>behind</b> a bullet/header node! <br>
	 * <br>
	 * <i>This method is separated in two parts!</i> The inital part can be found in
	 * the {@link #addEntry addEntry} method.
	 *
	 * @param newEntries
	 * @param modifications
	 */
	private void addEntries(String newEntries, String modifications, String comment) {
		// at the end we need this to check for changes
		boolean modified = false;
		// counter for inserting the new node, used below
		int childcount = 0;
		// remember the last added entry's timestamp
		String lastadded = null;
		// get the selected node, so we know where to insert the new entry
		DefaultMutableTreeNode insert = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		// if we have selected an entry, make sure to get the parent as insert-point
		// else we have selected a parent (bullet/header). the entry should be inserted
		// at
		// first posiion after the bullet.
		if (!insert.getAllowsChildren()) {
			DefaultMutableTreeNode parent = (DefaultMutableTreeNode) insert.getParent();
			// get the index of the selected child (i.e. the selected entry)
			// and add one, so the entry is inserted *after* the current selected entry
			childcount = parent.getIndex(insert) + 1;
			// and set the insert-value to the parent
			insert = parent;
		}
		// retrieve arrays from the text-input
		int[] entries = Tools.retrieveEntryNumbersFromInput(newEntries, dataObj.getCount(Daten.ZKNCOUNT));
		// here we store all found entries that have been added, so we can afterwards
		// iterate
		// this array to find the multiple entries for the above linked-list
		// we do this in two steps, because we want to search all entries within one
		// desktop,
		// that means: we want to go through all desktops (the outer loop), and inside
		// this
		// loop we want to go through all entries (the inner loop). but below, we are
		// iterating
		// all entries, so the desktop-iteration would be the inner-loop. this is not
		// intended,
		// because we want to sort the multiple entries according to an ordered
		// desktop-list,
		// which requires iterating the desktops as outer loop.
		LinkedList<Integer> multipleEntries = new LinkedList<>();
		// init multiple message flag
		showMultipleEntryMsg = true;
		// check for valid user-input
		if (entries != null) {
			for (int cnt : entries) {
				// check whether entry already exists
				if (noDoubleEntries(insert, cnt)) {
					// go through all desktops and check whether the current entry already exists.
					// if yes, add added entry to our linked list.
					for (int me = 0; me < desktopObj.getCount(); me++) {
						if (desktopObj.desktopContainsEntry(me, cnt)) {
							multipleEntries.add(cnt);
						}
					}
					// add entry to desktop (xml-file)
					lastadded = desktopObj.addEntry(TreeUtil.getNodeTimestamp(insert), String.valueOf(cnt), childcount);
					// check whether we also have modifications to add
					if (modifications != null && !modifications.isEmpty()) {
						desktopObj.addModifiedEntry(lastadded, modifications);
					}
					if (comment != null && !comment.isEmpty()) {
						desktopObj.setComment(lastadded, comment);
					}
					// remember that we have changes
					modified = true;
					// increase counter to indicate next entry
					childcount++;
				}
			}
		}
		// update treeview if we have changes
		if (modified) {
			// update treeview
			updateTreeView();
			// and re-select initial entry/bullet
			selectTreePath(lastadded);
			// show message box in case we have multiple occurences of entries...
			showMultipleOccurencesMessage(Tools.retrieveDoubleEntries(desktopObj, multipleEntries));
		}
	}

	private void showMultipleOccurencesMessage(List<Tools.DesktopDuplicates> list) {
		// if we have any multiple occurences, the stringbuilder must be longer than 0
		multipleOccurencesMessage = Tools.prepareDoubleEntriesMessage(list);
		// check whether we have any multiple occurences...
		if (multipleOccurencesMessage != null) {
			// check whether this dialog should be displayed at all...
			if (!settingsObj.getHideMultipleDesktopOccurencesDlg()) {
				multipleOccurencesMessage = resourceMap.getString("showMultipleEntriesOnDesktop") + lineseparator
						+ lineseparator + multipleOccurencesMessage;
				if (null == multipleOccurencesDlg) {
					// create a new dialog with the desktop-dialog, passing some initial values
					multipleOccurencesDlg = new CShowMultipleDesktopOccurences(this, settingsObj, false,
							multipleOccurencesMessage);
					// center window
					multipleOccurencesDlg.setLocationRelativeTo(null);
				} else {
					multipleOccurencesDlg.setInfoMsg(multipleOccurencesMessage);
				}
				// show window
				ZettelkastenApp.getApplication().show(multipleOccurencesDlg);
			} // if not, just display icon
			else {
				jButtonShowMultipleOccurencesDlg.setVisible(true);
			}
		}
	}

	@Action
	public void openMultipleOccurencesMessageDlg() {
		if (multipleOccurencesMessage != null) {
			multipleOccurencesMessage = resourceMap.getString("showMultipleEntriesOnDesktop") + lineseparator
					+ lineseparator + multipleOccurencesMessage;
			if (null == multipleOccurencesDlg) {
				// create a new dialog with the desktop-dialog, passing some initial values
				multipleOccurencesDlg = new CShowMultipleDesktopOccurences(this, settingsObj, false,
						multipleOccurencesMessage);
				// center window
				multipleOccurencesDlg.setLocationRelativeTo(null);
			} else {
				multipleOccurencesDlg.setInfoMsg(multipleOccurencesMessage);
			}
			// show window
			ZettelkastenApp.getApplication().show(multipleOccurencesDlg);
			// hide button
			jButtonShowMultipleOccurencesDlg.setVisible(false);
		}
	}

	/**
	 * This method adds entries, indicated by their index-numbers, to the desktop.
	 * this method is usually used to add entries to the desktop from other windows,
	 * like main-window or searchresults-window etc.
	 *
	 * @param entries the entry-numbers in an integer-array
	 */
	public void addEntries(int[] entries) {
		// when we have no entries, leave
		if ((null == entries) || (entries.length < 1)) {
			return;
		}
		// if we don't have any desktop created yet, tell the user to do so
		// before adding new entries...
		while (desktopObj.getCount() < 1) {
			// ask user whether a new desktop should be created...
			int option = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForNewDesktopMsg"),
					resourceMap.getString("askForNewDesktopTitle"), JOptionPane.YES_NO_OPTION,
					JOptionPane.PLAIN_MESSAGE);
			// if no, leave method...
			if (JOptionPane.NO_OPTION == option) {
				return;
			}
			// else create new desktop
			newDesktop();
			// when the user added a new desktop, select it
			if (desktopObj.getCount() >= 1) {
				TreePath tp = new TreePath(jTreeDesktop.getModel().getRoot());
				jTreeDesktop.setSelectionPath(tp);
			}
		}
		// if we don't have any bullets created yet, tell the user to do so
		// before adding new entries...
		while (!desktopObj.desktopHasBullets(desktopObj.getCurrentDesktopNr())) {
			// ask user whether a new bullet should be created...
			int option = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForNewBulletMsg"),
					resourceMap.getString("askForNewBulletTitle"), JOptionPane.YES_NO_OPTION,
					JOptionPane.PLAIN_MESSAGE);
			// if no, leave method
			if (JOptionPane.NO_OPTION == option) {
				return;
			}
			// else add bullet
			addBullet();
		}
		// if a valid node is selected, add entries
		if (isNodeSelected()) {
			// create a new stringbuilder
			StringBuilder sb = new StringBuilder();
			// iterate the array with all entries
			for (int e : entries) {
				// append entry-number
				sb.append(e);
				// and a comma
				sb.append(",");
			}
			// delete last comma
			if (sb.length() > 1) {
				sb.setLength(sb.length() - 1);
			}
			// add entries
			addEntries(sb.toString());
		} else {
			// copy entries to "clipboard", so the user can paste them after selecting a
			// bullet or node.
			clipEntries = entries;
			// tell user that a selection has to be made...
			JOptionPane.showMessageDialog(this, resourceMap.getString("errSelectionNeededMsg"),
					resourceMap.getString("errSelectionNeededTitle"), JOptionPane.PLAIN_MESSAGE);
		}
	}

	/**
	 * This action is enabled, when an entry has follower-entries (Luhmann-Numbers).
	 * If a user performs this action, all entry's follower-entries
	 * (Luhmann-Numbers) are added behind this entry.
	 */
	@Action(enabledProperty = "luhmannNodeSelected")
	public void addLuhmann() {
		addEntries(dataObj.getSubEntriesCsv(getSelectedEntryNumber()));
	}

	/**
	 * This action is enabled, when an entry has follower-entries (Luhmann-Numbers).
	 * If a user performs this action, all entry's follower-entries
	 * (Luhmann-Numbers) are added behind this entry.
	 */
	@Action(enabledProperty = "luhmannNodeSelected")
	public void addLuhmannComplete() {
		// init string builder
		luhmannnumbers = new StringBuilder();
		// get recursive Luhmann-Numbers
		fillLuhmannNumbers(getSelectedEntryNumber());
		// add them...
		if (luhmannnumbers.length() > 0) {
			// delete last comma
			luhmannnumbers.setLength(luhmannnumbers.length() - 1);
			// add entries to treeview
			addEntries(luhmannnumbers.toString());
		}
	}

	/**
	 * This method recursively retrieves all follower- and sub-follower-numbers
	 * (Luhmann-Numbers) of an entry and adds them to a stringbuilder. This method
	 * is needed for the {@link #addLuhmann addLuhmann}-Action that adds these
	 * follower-numbers to the treeview, directly behind the selected entry.
	 *
	 * @param zettelpos the number of the selected entry
	 */
	private void fillLuhmannNumbers(int zettelpos) {
		// get the text from the luhmann-numbers
		String lnr = dataObj.getSubEntriesCsv(zettelpos);
		// if we have any luhmann-numbers, go on...
		if (!lnr.isEmpty()) {
			String[] lnrs = lnr.split(",");
			// go throughh array of current luhmann-numbers
			for (String exist : lnrs) {
				// copy all values to an array
				luhmannnumbers.append(exist);
				luhmannnumbers.append(",");
				// check whether luhmann-value exists, by re-calling this method
				// again and go through a recusrive loop
				fillLuhmannNumbers(Integer.parseInt(exist));
			}
		}
	}

//    /**
//     * This method recursively retrieves all follower- and sub-follower-numbers
//     * (Luhmann-Numbers) of an entry and adds them to a stringbuilder. This method
//     * is needed for the {@link #addLuhmann addLuhmann}-Action that adds these
//     * follower-numbers to the treeview, directly behind the selected entry.
//     * 
//     * @param zettelpos the number of the selected entry
//     */
//    private String fillLuhmannNumbersWithBullets(int zettelpos, String timestamp) {
//        String lastadded = timestamp;
//        // get the text from the luhmann-numbers
//        String lnr = dataObj.getLuhmannNumbers(zettelpos);
//        // if we have any luhmann-numbers, go on...
//        if (!lnr.isEmpty()) {
//            String[] lnrs = lnr.split(",");
//            // go throughh array of current luhmann-numbers
//            for (String exist : lnrs) {
//                // add entry to desktop (xml-file)
//                lastadded = desktopObj.addEntry(timestamp, exist, 0);
//                
//                if (dataObj.hasLuhmannNumbers(Integer.parseInt(exist))) {
//                    lastadded = desktopObj.addBullet(lastadded, "Ebene " + exist);
//                    // check whether luhmann-value exists, by re-calling this method
//                    // again and go through a recusrive loop
//                    fillLuhmannNumbersWithBullets(Integer.parseInt(exist), lastadded);
//                }
//            }
//        }
//        return (lastadded);
//    }
	/**
	 * This method is called from "addEntry" and checks whether an entry-number
	 * already exists as a child of that parent.
	 *
	 * @param parent the insert-parent, where the entry should be inserted as child
	 * @param nr     the number of the entry that should be inserted
	 * @return {@code true} if the entry "nr" already exists as child of "parent".
	 */
	private boolean noDoubleEntries(DefaultMutableTreeNode parent, int nr) {
		// got through all parent's children
		for (int counter = 0; counter < parent.getChildCount(); counter++) {
			// get child
			DefaultMutableTreeNode doublechild = (DefaultMutableTreeNode) parent.getChildAt(counter);
			// retrieve the node's text and extract the entry-number
			int childnr = TreeUtil.extractEntryNumberFromNode(doublechild);
			// compare child's text with newBullet-text
			if (childnr == nr) {
				// if we found a match, tell user about cancelling
				if (showMultipleEntryMsg) {
					JOptionPane.showMessageDialog(this, resourceMap.getString("errEntryExistsMsg"),
							resourceMap.getString("errEntryExistsTitle"), JOptionPane.PLAIN_MESSAGE);
					showMultipleEntryMsg = false;
				}
				return false;
			}
		}
		return true;
	}

	/**
	 * Exports the desktop-data to a file, i.e. the content will be written to a
	 * file "as it is" (wysiwyg). unlink the typical export method, this export
	 * method also export bullet-point-headings, invisible entry-titles, modified
	 * entries etc. some of these features are not supported by the usual
	 * export-method.
	 */
	@Action
	public void exportDesktop() {
		export(desktopObj.getCurrentDesktopElement(), (DefaultMutableTreeNode) jTreeDesktop.getModel().getRoot());
	}

	@Action
	public void importArchivedDesktop() {
		// create document
		Document archive = new Document();
		// retrieve last used importdirectory
		File importdir = settingsObj.getMainDataFile();
		// let user choose filepath
		File filepath = FileOperationsUtil.chooseFile(this,
				(settingsObj.isMacStyle()) ? FileDialog.LOAD : JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY,
				(null == importdir) ? null : importdir.getPath(), (null == importdir) ? null : importdir.getName(),
				resourceMap.getString("openArchiveTitle"), new String[] { ".zip" }, "Zip", settingsObj);
		// if we have a valid file, go on
		if (filepath != null && filepath.exists()) {
			ZipInputStream zip = null;
			// open the zip-file
			try {
				zip = new ZipInputStream(new FileInputStream(filepath));
				ZipEntry entry;
				// now iterate the zip-file, searching for the requested file in it
				while ((entry = zip.getNextEntry()) != null) {
					// get filename of zip-entry
					String entryname = entry.getName();
					// if the found file matches the requested one, start the SAXBuilder
					if (entryname.equals(Constants.archivedDesktopFileName)) {
						try {
							SAXBuilder builder = new SAXBuilder();
							archive = builder.build(zip);
							break;
						} catch (JDOMException e) {
							Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage());
						}
					}
				}
				// tell about success
				Constants.zknlogger.log(Level.INFO, "Desktop archive successfully opened.");
			} catch (IOException e) {
				Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage());
				// show error message dialog
				JOptionPane.showMessageDialog(this, resourceMap.getString("openArchiveDlgErr"),
						resourceMap.getString("openArchiveDlgTitle"), JOptionPane.PLAIN_MESSAGE);
				// and show error log
				zknframe.showErrorIcon();
				return;
			} finally {
				try {
					if (zip != null) {
						zip.close();
					}
				} catch (IOException e) {
					Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage());
				}
			}
			// init variables that indicate the success of the import-progress
			boolean finished = false;
			// we have a loop here, because the desktop-name of the imported archiv might
			// already exist.
			// in this case, the user can retry with new names, until a new name was
			// entered, or the
			// user cancels the action
			while (!finished) {
				// import archive
				int result = desktopObj.importArchivedDesktop(archive);
				// here we go on in case the desktop-name of the imported archive
				// already exists. in this case, the user shoould rename the archive
				if (DesktopData.IMPORT_ARCHIVE_ERR_DESKTOPNAME_EXISTS == result) {
					// desktop-name already existed, so desktop was not added...
					JOptionPane.showMessageDialog(this,
							resourceMap.getString("errDesktopNameExistsMsg",
									archive.getRootElement().getAttributeValue("name")),
							resourceMap.getString("errDesktopNameExistsTitle"), JOptionPane.PLAIN_MESSAGE);
					// user-input for new desktop-description
					String newDeskName = JOptionPane.showInputDialog(this, resourceMap.getString("newDesktopMsg"),
							resourceMap.getString("newDesktopTitle"), JOptionPane.PLAIN_MESSAGE);
					// check for valid-return value, or if the user cancelled the action
					if (newDeskName != null && !newDeskName.isEmpty()) {
						// if everything was ok, set new name
						archive.getRootElement().setAttribute("name", newDeskName);
					} else {
						// else user has cancelled process
						JOptionPane.showMessageDialog(this, resourceMap.getString("openArchiveCancelled"),
								resourceMap.getString("openArchiveDlgTitle"), JOptionPane.PLAIN_MESSAGE);
						return;
					}
				} else if (DesktopData.IMPORT_ARCHIVE_ERR_OTHER == result) {
					// tell user about problem
					JOptionPane.showMessageDialog(this, resourceMap.getString("openArchiveError"),
							resourceMap.getString("openArchiveDlgTitle"), JOptionPane.PLAIN_MESSAGE);
					// and show error log
					zknframe.showErrorIcon();
					return;
				} else if (DesktopData.IMPORT_ARCHIVE_OK == result) {
					// everything is ok, so quit while-loop
					finished = true;
				}
			}
			// show success
			JOptionPane.showMessageDialog(this, resourceMap.getString("openArchiveOK"),
					resourceMap.getString("openArchiveTitle"), JOptionPane.PLAIN_MESSAGE);
			// and update combo box
			updateComboBox(false);
		}
	}

	/**
	 * This method archives the currently active desktop to a zipped xml-file. This
	 * method saves the current desktop-data, the related notes for this desktop and
	 * possible modified entries.<br>
	 * <br>
	 * Archive files can be imported as well (see {@link #importArchivedDesktop()
	 * importArchivedDesktop()}).
	 */
	@Action
	public void archiveDesktop() {
		// retrieve data-filepath
		File datafp = settingsObj.getMainDataFile();
		// convert to string, and cut off filename by creating a substring that cuts off
		// everything after the last separator char
		String datafilepath = (datafp != null)
				? datafp.getPath().substring(0, datafp.toString().lastIndexOf(java.io.File.separator) + 1)
				: "";
		// ... to cut off extension
		if (!datafilepath.isEmpty()) {
			datafilepath = datafilepath + desktopObj.getCurrentDesktopName()
					+ resourceMap.getString("archiveDesktopSuffix");
		}
		// create new path
		File exportdir = new File(datafilepath);
		// here we open a swing filechooser, in case the os ist no mac aqua
		File filepath = FileOperationsUtil.chooseFile(this,
				(settingsObj.isMacStyle()) ? FileDialog.SAVE : JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY,
				exportdir.getPath(), exportdir.getName(), resourceMap.getString("fileDialogTitleSave"),
				new String[] { ".zip" }, "Zip", settingsObj);
		if (filepath != null) {
			// add fileextenstion, if necessay
			if (!filepath.getName().endsWith(".zip")) {
				filepath = new File(filepath.toString() + ".zip");
			}
			// check whether file already exists
			if (filepath.exists()) {
				// file exists, ask user to overwrite it...
				int optionDocExists = JOptionPane.showConfirmDialog(null,
						resourceMap.getString("askForOverwriteFileMsg", filepath.getName()),
						resourceMap.getString("askForOverwriteFileTitle"), JOptionPane.YES_NO_OPTION,
						JOptionPane.PLAIN_MESSAGE);
				// if the user does *not* choose to overwrite, quit...
				if (optionDocExists != JOptionPane.YES_OPTION) {
					// don't show "export was OK" message in main frame
					return;
				}
			}
			// create desktop-archive-XML-document
			Document archiveddesktop = desktopObj.archiveDesktop(desktopObj.getCurrentDesktopName());
			// check whether an error occured
			if (null == archiveddesktop) {
				// tell user about error
				JOptionPane.showMessageDialog(this, resourceMap.getString("archiveErrMsg"),
						resourceMap.getString("archiveErrTitle"), JOptionPane.PLAIN_MESSAGE);
				zknframe.showErrorIcon();
				return;
			}
			// export and zip file
			ZipOutputStream zip = null;
			// open the outputstream
			try {
				zip = new ZipOutputStream(new FileOutputStream(filepath));
				// I first wanted to use a pretty output format, so advanced users who
				// extract the data file can better watch the xml-files. but somehow, this
				// lead to an error within the method "retrieveElement" in the class
				// "CDaten.java",
				// saying the a org.jdom.text cannot be converted to org.jdom.element?!?
				// XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
				XMLOutputter out = new XMLOutputter();
				// save archived desktop
				zip.putNextEntry(new ZipEntry(Constants.archivedDesktopFileName));
				out.output(archiveddesktop, zip);
			} catch (IOException | SecurityException e) {
				Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage());
				JOptionPane.showMessageDialog(this, resourceMap.getString("archiveErrMsg"),
						resourceMap.getString("archiveErrTitle"), JOptionPane.PLAIN_MESSAGE);
				zknframe.showErrorIcon();
				return;
			} finally {
				try {
					if (zip != null) {
						zip.close();
					}
				} catch (IOException e) {
					Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage());
				}
			}
			JOptionPane.showMessageDialog(this, resourceMap.getString("archiveOkMsg"),
					resourceMap.getString("archiveOkTitle"), JOptionPane.PLAIN_MESSAGE);
		}
	}

	/**
	 * Exports the desktop-data to a file, i.e. the content will be written to a
	 * file "as it is" (wysiwyg). unlink the typical export method, this export
	 * method also export bullet-point-headings, invisible entry-titles, modified
	 * entries etc. some of these features are not supported by the usual
	 * export-method.
	 *
	 * @param startelement the starting point for the jTree-enumeration, either the
	 *                     root element or a bullet (if only a bullet should be
	 *                     exported, see {@link #exportDesktopBullet()
	 *                     exportDesktopBullet()}).
	 * @param startnode    the starting point for the jTree-enumeration, either the
	 *                     root node or a bullet (if only a bullet should be
	 *                     exported, see {@link #exportDesktopBullet()
	 *                     exportDesktopBullet()}).
	 */
	private void export(Element startelement, DefaultMutableTreeNode startnode) {
		// opens the Export Dialog. This Class is responsible
		// for getting the relevant export data. the export task
		// itself (background task) will be started as another dialog,
		// when this one is closed
		// now open the export-dialog
		if (null == exportWindow) {
			// get parent und init window
			exportWindow = new CDesktopExport(this, settingsObj, bibtexObj);
			// center window
			exportWindow.setLocationRelativeTo(this);
		}
		ZettelkastenApp.getApplication().show(exportWindow);
		// Here the data (filepath, filetype) from the export window
		// will be passed to another dialog window, which starts the
		// background task. these dialogs are separated because it looks
		// better to have a background task with progress bar in an own,
		// smaller dialog
		//
		// first check for valid return value. export is only started,
		// when the previous dialog wasn't cancelled or simply closed
		if (Constants.RETURN_VALUE_CONFIRM == exportWindow.getReturnValue()) {
			// when the user wants to export into PDF or LaTex, open a new dialog where the
			// user
			// can make some extra settings like page settings and font-sizes.
			if (ExportTools.isExportSettingsOk(this, settingsObj, exportWindow.getExportType())) {
				// if dialog window isn't already created, do this now
				if (null == taskDlg) {
					// create list that will contain all entries which should be exported
					ArrayList<Object> liste = new ArrayList<>();
					// here we recursively create the list of headlines and entry-numbers
					// from the current desktop
					createExportEntries(startelement, liste);
					// open export dialog
					// get parent und init window
					taskDlg = new TaskProgressDialog(this, TaskProgressDialog.TASK_EXPORTDATA, taskdata, dataObj,
							bookmarksObj, desktopObj, settingsObj, bibtexObj, null, exportWindow.getFilePath(), liste,
							exportWindow.getExportType(), 0, ';', startnode, false, false,
							exportWindow.getExportBibTex(), false, exportWindow.getExportToc(), isHeadingVisible,
							isEntryNumberVisible);
					// center window
					taskDlg.setLocationRelativeTo(this);
				}
				ZettelkastenApp.getApplication().show(taskDlg);
				// dispose the window and clear the object
				taskDlg.dispose();
				taskDlg = null;
				// else tell user that everything went fine
				if (taskdata.showExportOkMessage()) {
					JOptionPane.showMessageDialog(this, resourceMap.getString("exportOkMsg"),
							resourceMap.getString("exportOkTitle"), JOptionPane.PLAIN_MESSAGE);
				}
			}
		}
		// we have to manually dispose the window and release the memory
		// because next time this method is called, the showKwlDlg is still not null,
		// i.e. the constructor is not called (because the if-statement above is not
		// true)
		exportWindow.dispose();
		exportWindow = null;
	}

	/**
	 * This method exports not a complete desktop, but the selected bullets with all
	 * its sub-entries (child-nodes) to a file.
	 */
	@Action(enabledProperty = "bulletSelected")
	public void exportDesktopBullet() {
		// only export subentries, if a bullet-point is selected.
		if (!isBulletSelected()) {
			return;
		}
		// find starting-element (selected bullet) from timestamp
		String timestamp = getSelectedNodeTimestamp();
		// and export data
		export(desktopObj.findEntryElementFromTimestamp(desktopObj.getCurrentDesktopElement(), timestamp),
				(DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent());
	}

	/**
	 * This method exports all desktops to a file. Unlike the typical
	 * export-function for desktop-data (see {@link #exportDesktop()
	 * exportDesktop()}, this method does not export the desktop-data "as it is"
	 * (including modified entries, see {@link #modifiyEntry() modifiyEntry()}), but
	 * only the simple entry-contents.<br>
	 * <br>
	 * While the typical desktop-export-functions call the
	 * {@link #export(org.jdom.Element, javax.swing.tree.DefaultMutableTreeNode)
	 * export()} method, this method calls the export-method from the mainframe.
	 */
	@Action
	public void exportMultipleDesktop() {
		// check whether multiple desktops available
		if (desktopObj.getCount() < 2) {
			return;
		}

		if (null == desktopMultipleExportDlg) {
			// create a new dialog with the desktop-dialog, passing some initial values
			desktopMultipleExportDlg = new CDesktopMultipleExport(this, desktopObj, settingsObj);
			// center window
			desktopMultipleExportDlg.setLocationRelativeTo(this);
		}
		// show window
		ZettelkastenApp.getApplication().show(desktopMultipleExportDlg);
		// check for return-value
		if (desktopMultipleExportDlg.getChosenDesktops() != null
				&& desktopMultipleExportDlg.getChosenDesktops().length > 0) {
			// create list that will contain all entries which should be exported
			ArrayList<Object> liste = new ArrayList<>();
			// iterate all chosen desktop-names
			for (String desktopname : desktopMultipleExportDlg.getChosenDesktops()) {
				// here we recursively create the list of headlines and entry-numbers
				// from the current desktop
				createExportEntries(desktopObj.getDesktopElement(desktopname), liste);
			}
			// call export-method and export the entries.
			zknframe.exportEntries(liste);
		}
		// delete the windows
		desktopMultipleExportDlg.dispose();
		desktopMultipleExportDlg = null;
	}

	/**
	 * This method "exports" all entries of the current desktop as search results,
	 * i.e. all entry-numbers are shown in the search results window.<br>
	 * <br>
	 * You can also export just the entries of a selected bullet and all its
	 * sub-entries (child-nodes) as search result, see
	 * {@link #exportBulletToSearch() exportBulletToSearch()}.
	 */
	@Action
	public void exportToSearch() {
		zknframe.exportDesktopToSearch(desktopObj.retrieveDesktopEntries(desktopObj.getCurrentDesktopNr()),
				desktopObj.getCurrentDesktopName());
	}

	/**
	 * This method "exports" all entries of the currently selected bullet and all
	 * its sub-entries (child-nodes) as search results, i.e. all related
	 * entry-numbers are shown in the search results window.<br>
	 * <br>
	 * You can also export the entries of the complete desktop as search result, see
	 * {@link #exportToSearch() exportToSearch()}.
	 */
	@Action(enabledProperty = "bulletSelected")
	public void exportBulletToSearch() {
		if (isBulletSelected()) {
			// retrieve selected node and its timestamp
			String timestamp = getSelectedNodeTimestamp();
			// here we recursively create the list of headlines and entry-numbers
			// from the current desktop
			zknframe.exportDesktopToSearch(
					desktopObj.retrieveBulletEntries(
							desktopObj.findEntryElementFromTimestamp(desktopObj.getCurrentDesktopElement(), timestamp)),
					desktopObj.getCurrentDesktopName());
		}
	}

	/**
	 * This method shows all entries that are <b>not</b> used in the current desktop
	 * as search results, i.e. all entry-numbers that do not appear in the current
	 * desktop are shown in the search results window.
	 */
	@Action
	public void exportMissingToSearch() {
		// retrieve all entry-numbers from current desktop
		int[] currentdesktopentries = desktopObj.retrieveDesktopEntries(desktopObj.getCurrentDesktopNr());
		// check for valid return value
		if (currentdesktopentries != null && currentdesktopentries.length > 0) {
			// create new integer-array
			ArrayList<Integer> expvalues = new ArrayList<>();
			// go through all entry-numbers
			for (int cnt = 1; cnt <= dataObj.getCount(Daten.ZKNCOUNT); cnt++) {
				// if entry-number is *not* on the desktop...
				if (!isInArray(cnt, currentdesktopentries)) {
					// ... add it to our result-array
					expvalues.add(cnt);
				}
			}
			// if we have any results, go on...
			if (expvalues.size() > 0) {
				// create return value
				int[] retval = new int[expvalues.size()];
				// and copy all integer-values from the list to that array
				for (int cnt = 0; cnt < retval.length; cnt++) {
					retval[cnt] = expvalues.get(cnt);
				}
				zknframe.exportDesktopToSearch(retval, desktopObj.getCurrentDesktopName());
			}
		}
	}

	/**
	 * This method checks for the occurence of the value {@code nr} inside the array
	 * {@code arr}.
	 *
	 * @param nr  the integer-value we are looking for
	 * @param arr the integer-array, which mightt contain{@code nr}
	 * @return {@code true} if {@code nr} was found inside {@code arr},
	 *         {@code false} otherwise.
	 */
	private boolean isInArray(int nr, int[] arr) {
		// check for valid array
		if (arr != null && arr.length > 0) {
			// go through whole array
			for (int cnt = 0; cnt < arr.length; cnt++) {
				// if we found the value "nr" inside the array "arr", return true
				if (arr[cnt] == nr) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * This methods checks whether a selected entry is the last entry in the list of
	 * a bullet's child-nodes.
	 *
	 * @return {@code true} if the selected entry is the last entry in a list of
	 *         child-nodes, false otherwise
	 */
	private boolean isLastNode() {
		// if no node selected, return...
		if (!isNodeSelected()) {
			return false;
		}
		// get the selected node, so we know where to insert the new bullet
		DefaultMutableTreeNode selection = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		// enumerate all children of the node's parent's children...
		Enumeration<?> children = node.getParent().children();
		while (children.hasMoreElements()) {
			try {
				// get each child
				node = (DefaultMutableTreeNode) children.nextElement();
				// if the child of the enumeration equals the selection...
				if (node.equals(selection)) {
					// get next node after selected entry
					node = (DefaultMutableTreeNode) children.nextElement();
					// if the selected entry has another entry behind, return false
					// otherwise true
					return (!isBulletSelected()) && (node.getAllowsChildren());
				}
			} catch (NoSuchElementException e) {
				// if there is no entry after the selected one, return true
				return true;
			}
		}
		return false;
	}

	/**
	 * This methods checks whether a selected entry is the first entry in the list
	 * of a bullet's child-nodes.
	 *
	 * @return {@code true} if the selected entry is the first entry in a list of
	 *         child-nodes, false otherwise
	 */
	private boolean isFirstNode() {
		// if no node selected, return...
		if (!isNodeSelected()) {
			return false;
		}
		// get the selected node, so we know where to insert the new bullet
		DefaultMutableTreeNode selection = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		// if the selection is a node-entry...
		// ...return true when selected entry equals the first child-node of the
		// selected entry's parent
		if (!isBulletSelected()) {
			return (0 == selection.getParent().getIndex(selection));
			// return (selection.equals(selection.getParent().getChildAt(0)));
		} // else if the selection is a bullet-point...
		else {
			// get the selected node's index
			int index = selection.getParent().getIndex(selection);
			// if index is 0, it is the first node.
			if (0 == index) {
				return true;
			}
			// else check whether the node before the selection is a bullet and return
			// false, if it is...
			return !selection.getParent().getChildAt(index - 1).getAllowsChildren();
		}
	}

	/**
	 * Closes the window, i.e. makes it invisible
	 */
	@Action
	public void closeWindow() {
		// save current notes
		desktopObj.setDesktopNotes(1, jTextArea1.getText());
		desktopObj.setDesktopNotes(2, jTextArea2.getText());
		desktopObj.setDesktopNotes(3, jTextArea3.getText());
		// save last used desktop nr
		settingsObj.setLastUsedDesktop(jComboBoxDesktop.getSelectedIndex());
		// check whether memory usage is logged. if so, tell logger that new entry
		// windows was opened
		if (settingsObj.isMemoryUsageLogged) {
			// log info
			Constants.zknlogger.log(Level.INFO, "Memory usage logged. Desktop Window closed.");
		}
		// dispose window
		dispose();
		setVisible(false);
	}

	/**
	 * This method modifies an entry, but these changes are only applied to the
	 * desktop-view. the original entry's content in the main-database is not
	 * changed. <br>
	 * <br>
	 * This is helpful when the user wants to "connect" entries by adding some words
	 * or paragraphs, which is only necessary for a readable text on the desktop,
	 * while the original entries should be left unmodified.
	 */
	@Action(enabledProperty = "entryNodeSelected")
	public void modifiyEntry() {
		// check whether a correct entry node was selected or not...
		if (!isEntryNodeSelected()) {
			return;
		}

		// check whether an entry is already being edited, i.e. the edit-window is
		// already created
		if (isEditModeActive) {
			// if so, bring that window to the front
			modifyEntryDlg.toFront();
		} // else create a new window and display it.
		else {
			// get the selected node, to tell the getComment method wether we have a bullet
			// or an entry selected
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
			// retrieve and store edit-timestamp
			editModeTimeStamp = TreeUtil.getNodeTimestamp(node);
			// retrieve content from modified entry, if any...
			String oldcontent = desktopObj.retrieveModifiedEntryContentFromTimestamp(editModeTimeStamp);
			// check for any modified content. if we have no content, retrieve entry's
			// original content instead
			if (null == oldcontent || oldcontent.isEmpty()) {
				// get original entry content
				oldcontent = dataObj.getZettelContent(TreeUtil.extractEntryNumberFromNode(node));
			}
			// create a new dialog with the bigger edit-field, passing some initial values
			modifyEntryDlg = new CModifyDesktopEntry(this, settingsObj, spellObj, stenoObj, accKeys, oldcontent);
			// center window
			modifyEntryDlg.setLocationRelativeTo(this);
			ZettelkastenApp.getApplication().show(modifyEntryDlg);

			// edit window was initialized
			isEditModeActive = true;
		}
	}

	/**
	 * This method replaces an original's entry's content with the modifications
	 * that have been made for this entry on the desktop.
	 */
	@Action(enabledProperty = "modifiedEntryNode")
	public void applyModificationsToOriginalEntry() {
		// as whether original entry's content should really be replaced
		int option = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForApplyModificationsMsg"),
				resourceMap.getString("askForApplyModificationsTitle"), JOptionPane.YES_NO_OPTION,
				JOptionPane.PLAIN_MESSAGE);
		// if yes, go on
		if (JOptionPane.YES_OPTION == option) {
			// retrieve selected entry-number
			int nr = getSelectedEntryNumber();
			// check for valid value
			if (nr != -1) {
				// retrieve timestamp of selected entry
				String timestamp = getSelectedNodeTimestamp();
				// retrieve modified content
				String content = desktopObj.retrieveModifiedEntryContentFromTimestamp(timestamp);
				// and change entry
				dataObj.setZettelContent(nr, content, true);
				// remove modified entry from modification list
				desktopObj.deleteModifiedEntry(timestamp);
				// check whether modified entry is currently displayed. if so,
				// update view in mainframe...
				if (nr == zknframe.displayedZettel) {
					zknframe.updateDisplay();
				}
			}
		}
	}

	/**
	 * This method replaces an original's entry's content with the modifications
	 * that have been made for this entry on the desktop.
	 */
	@Action
	public void applyAllModificationsToOriginalEntries() {
		// as whether original entry's content should really be replaced
		int option = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForApplyModificationsMsg"),
				resourceMap.getString("askForApplyModificationsTitle"), JOptionPane.YES_NO_OPTION,
				JOptionPane.PLAIN_MESSAGE);
		// if yes, go on
		if (JOptionPane.YES_OPTION == option) {
			// retrieve all entry timestamps from desktop
			String[] alltimestamps = desktopObj.retrieveEntryTimestampsFromDesktop();
			// check for valid value
			if (alltimestamps != null) {
				// iterate array
				for (String ats : alltimestamps) {
					// get entry number
					int enr = desktopObj.findEntryNrFromTimestamp(ats);
					// retrieve modified content
					String content = desktopObj.retrieveModifiedEntryContentFromTimestamp(ats);
					// check for valid values
					if (enr != -1 && content != null) {
						// and change entry
						dataObj.setZettelContent(enr, content, true);
						// remove modified entry from modification list
						desktopObj.deleteModifiedEntry(ats);
						// check whether modified entry is currently displayed. if so,
						// update view in mainframe...
						if (enr == zknframe.displayedZettel) {
							zknframe.updateDisplay();
						}
					}
				}
			}
		}
	}

	/**
	 * This method is called after an entry was modified (see {@link #modifiyEntry()
	 * modifiyEntry()} and {@link #modifyEntryDlg modifyEntryDlg} for more details).
	 * Since the edit-window is modal, we need a message from that window when the
	 * editing is finished and when the changes can be applied to the desktop data.
	 * the edit-window calls this method to indicate the finishing of an
	 * edit-operation.
	 */
	public void finishedEditing() {
		// after closing the window, get the new value
		String newcontent = modifyEntryDlg.getModifiedEntry();
		boolean newconmodified = modifyEntryDlg.isModified();
		// delete the input-dialog
		modifyEntryDlg.dispose();
		modifyEntryDlg = null;

		// reset flag
		isEditModeActive = false;

		// check for valid return value
		if (newconmodified && newcontent != null && !newcontent.isEmpty()) {
			// change modified entry
			if (desktopObj.changeEntry(editModeTimeStamp, newcontent)) {
				// update menu-items
				updateToolbarAndMenu();
				// change updateflag
				setNeedsUpdate(true);
			} else {
				// if an error occured, tell user about it...
				JOptionPane.showMessageDialog(this, resourceMap.getString("errModifyEntryMsg"),
						resourceMap.getString("errModifyEntryTitle"), JOptionPane.PLAIN_MESSAGE);
			}
		}
	}

	// TODO kommentare von einträgen mit kopieren/verschieben
	/**
	 * Retrieves the entry-number of the selected entry and copies it to the
	 * internal clipboard. after that, the selected node is deleted.
	 */
	@Action(enabledProperty = "nodeSelected")
	public void cutNode() {
		if (isBulletSelected()) {
			// store value, so we know the clipboard does contain bullets
			clipBullet = true;
			// copy bullet's name into variable
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
			clipBulletName = node.toString();
			// tell the desktop-data-class that the selected bullet has to be stored
			// for later use
			desktopObj.cutBulletToClip(TreeUtil.getNodeTimestamp(node));
			// update view
			updateTreeView();
		} else {
			// retrieve selected entry.
			int nr = getSelectedEntryNumber();
			// if we have any entries, copy their numbers to the clipboard
			if (nr != -1) {
				// retrieve timestamp of selected node
				String ts = TreeUtil
						.getNodeTimestamp((DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent());
				// retrieve modifications of that entry, if any modifications were made
				clipModifiedEntryContent = desktopObj.retrieveModifiedEntryContentFromTimestamp(ts);
				// delete selected node
				deleteNode();
				// and copy the entrynumber to the clipboard
				clipEntries = new int[] { nr };
				// store value, so we know the clipboard does not contain bullets
				clipBullet = false;
			}
		}
		// update toolbars
		updateToolbarAndMenu();
	}

	/**
	 * Retrieves the entry-number of the selected entry and copies it to the
	 * internal clipboard.
	 */
	@Action(enabledProperty = "nodeSelected")
	public void copyNode() {
		if (isBulletSelected()) {
			// store value, so we know the clipboard does contain bullets
			clipBullet = true;
			// copy bullet's name into variable
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
			clipBulletName = node.toString();
			// tell the desktop-data-class that the selected bullet has to be stored
			// for later use
			desktopObj.copyBulletToClip(TreeUtil.getNodeTimestamp(node));
		} else {
			// retrieve selected entry.
			int nr = getSelectedEntryNumber();
			// if we have any entries, copy their numbers to the clipboard
			if (nr != -1) {
				// retrieve timestamp of selected node
				String ts = TreeUtil
						.getNodeTimestamp((DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent());
				// retrieve modifications of that entry, if any modifications were made
				clipModifiedEntryContent = desktopObj.retrieveModifiedEntryContentFromTimestamp(ts);
				// and copy the entrynumber to the clipboard
				clipEntries = new int[] { nr };
				// store value, so we know the clipboard does not contain bullets
				clipBullet = false;
			}
		}
		// update toolbars
		updateToolbarAndMenu();
	}

	/**
	 * This method pastes a node or bullet from the clipboard into the treeview.
	 * Relevant variables for this operation are:<br>
	 * <ul>
	 * <li>{@code clipBullet}, a boolean variable that indicates whether the
	 * internal clipboard is filled with entries (nodes) or a bullet</li>
	 * <li>{@code clipBulletName}, a string variable containing the name of the cut
	 * or copied bullet-point, in case we have a bullet-point in the clkipboard.
	 * this is need for checking if the bullet exists at that point where it should
	 * be inserted (pasted)</li>
	 * <li>{@code clipEntries}, an integer-array containing the entry-numbers of the
	 * entries that should be pasted in case we have entries (nodes) in the
	 * clipboard.</li>
	 * </ul>
	 */
	@Action(enabledProperty = "clipFilled")
	public void pasteNode() {
		// when we have a bullet-point in the clipboard, go on here...
		if (clipBullet) {
			// cut off id from clipbullet-timestamp-id
			int pos = clipBulletName.indexOf("[");
			// only continue if we found something...
			if (pos != -1) {
				// compare child's text with newBullet-text
				clipBulletName = clipBulletName.substring(0, pos).trim();
			}
			// first check, whether the bullet-point already exists as child where the user
			// wants to pase the bullet
			if (!checkIfBulletExists(clipBulletName)) {
				// get selection
				DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
				// if not, insert it.
				desktopObj.pasteBulletFromClip(getSelectedNodeTimestamp(), node.isRoot());
				// update treeview
				updateTreeView();
			}
		} // ...else if we have entries in the clipboard, add them now...
		else if ((clipEntries != null) && (clipEntries.length > 0)) {
			// check whether we have only one entry and modifications
			// this indicates a cut/copy and paste, so we use the other add-method
			// which also add modifications.
			if (1 == clipEntries.length) {
				addEntries(String.valueOf(clipEntries[0]), clipModifiedEntryContent, null);
			} else {
				addEntries(clipEntries);
			}
		}
	}

	/**
	 * This method moves the selected node in the jTree upwards, if possible.
	 */
	@Action(enabledProperty = "moveUpEnabled")
	public void moveNodeUp() {
		moveNode(Constants.MOVE_UP);
	}

	/**
	 * This method moves the selected node in the jTree downwards, if possible.
	 */
	@Action(enabledProperty = "moveDownEnabled")
	public void moveNodeDown() {
		moveNode(Constants.MOVE_DOWN);
	}

	/**
	 * This method moves the selected node up- or downwards, if possible, depending
	 * on the parameter {@code movement}.
	 *
	 * @param movement indicates whether the selected node in the jTree should be
	 *                 moved up- or downwards. use following constants:<br>
	 *                 - {@code CConstants.MOVE_UP}<br>
	 *                 - {@code CConstants.MOVE_DOWN}
	 */
	private void moveNode(int movement) {
		// retrieve timestamp from selected node
		String timestamp = getSelectedNodeTimestamp();
		// move element up
		desktopObj.moveElement(movement, timestamp);
		// update treeview
		updateTreeView();
		// re-select the previous path
		selectTreePath(timestamp);
		// update toolbars
		updateToolbarAndMenu();
	}

	/**
	 * This method selects the node in the jTree that matches the timestamp-id
	 * {@code timestamp}.
	 *
	 * @param timestamp the timestamp of the entry which node should be selected in
	 *                  the jTree.
	 */
	private void selectTreePath(String timestamp) {
		// get the root
		DefaultMutableTreeNode node = findNodeFromTimestamp((DefaultMutableTreeNode) jTreeDesktop.getModel().getRoot(),
				timestamp);
		// if we have a valid value...
		if (node != null) {
			// select node
			jTreeDesktop.setSelectionPath(new TreePath(node.getPath()));
		}
		// and bring focus back to window, if necessary
		this.toFront();
		jTreeDesktop.requestFocusInWindow();
	}

	/**
	 * This method recursevily traverses the jTree, starting at the position
	 * {@code node}, and tries to find an entry with the timestamp-id
	 * {@code timestamp}.
	 *
	 * @param node      the starting-point in the jTree, where this method searches
	 *                  through all (child-)elements.
	 * @param timestamp the timestamp-id of the requested entry
	 * @return the found node that matches the entry with the timestamp-id
	 *         {@code timestamp}, or {@code null} if nothing was found.
	 */
	private DefaultMutableTreeNode findNodeFromTimestamp(DefaultMutableTreeNode node, String timestamp) {
		// check whether the element "e" passed as parameter already has a
		// timestamp-attribute that
		// matches the parameter "t". if so, return that element.
		String ts = TreeUtil.getNodeTimestamp(node);
		if (ts != null && ts.equals(timestamp)) {
			return node;
		}
		// now go through all parts of the previously selected path
		Enumeration<?> children = node.children();
		// go through all children
		while (children.hasMoreElements()) {
			// get the child
			node = (DefaultMutableTreeNode) children.nextElement();
			// check whether element has a timestamp value at all, and if it matches the
			// parameter "t".
			ts = TreeUtil.getNodeTimestamp(node);
			if (ts != null && ts.equals(timestamp)) {
				return node;
			}
			// when the new element also has children, call this method again,
			// so we go through the strucuture recursively...
			if (node.getChildCount() > 0) {
				// if we have any child-elements, go into method again
				// to traverse recursevely all elements
				node = findNodeFromTimestamp(node, timestamp);
				// retrieve timestamp from returned node.
				ts = TreeUtil.getNodeTimestamp(node);
				// if we found a match, leave function and don't iterate any further elements
				if (ts != null && ts.equals(timestamp)) {
					return node; /* else return null; */

				}
			}
		}
		// retrieve timestamp from returned node.
		ts = TreeUtil.getNodeTimestamp(node);
		// and return either the node if timestamp matches or null if not.
		if (ts != null && ts.equals(timestamp)) {
			return node;
		} else {
			return null;
		}
	}

	/**
	 * This method updates the display, i.e. the whole page (the entries in
	 * html-formatting) is new created and then set to the jEditorPane. This action
	 * is only enabled whenever changes to the desktopstructure have been made, like
	 * inserting or renaming bullets, inserting or removing entries and so on...
	 */
	@Action(enabledProperty = "needsUpdate")
	public void updateView() {
		updateDisplay();
	}

	/**
	 * Activates or deactivates the fullscreen-mode, thus switching between
	 * fullscreen and normal view.
	 */
	@Action(enabledProperty = "fullScreenSupp")
	public void viewFullScreen() {
		// check whether fullscreen is possible or not...
		if (graphicdevice.isFullScreenSupported()) {
			// if we already have a fullscreen window, quit fullscreen
			if (graphicdevice.getFullScreenWindow() != null) {
				quitFullScreen();
			} // else show fullscreen window
			else {
				showFullScreen();
			}
		}
	}

	/**
	 * This method activates the fullscreen-mode, if it's not already activated yet.
	 * To have a fullscreen-window without decoration, the frame is disposed first,
	 * then the decoration will be removed and the window made visible again.
	 */
	private void showFullScreen() {
		// check whether fullscreen is supported, and if we currently have a
		// fullscreen-window
		if (graphicdevice.isFullScreenSupported() && null == graphicdevice.getFullScreenWindow()) {
			// dispose frame, so we can remove the decoration when setting full screen mode
			mainframe.dispose();
			// hide menubar
			jMenuBarDesktop.setVisible(false);
			// set frame non-resizable
			mainframe.setResizable(false);
			try {
				// remove decoration
				mainframe.setUndecorated(true);
			} catch (IllegalComponentStateException e) {
				Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage());
			}
			// show frame again
			mainframe.setVisible(true);
			// set fullscreen mode to this window
			graphicdevice.setFullScreenWindow(this);
		}
	}

	/**
	 * This method <i>de</i>activates the fullscreen-mode, if it's not already
	 * deactivated yet.
	 */
	private void quitFullScreen() {
		// check whether fullscreen is supported, and if we currently have a
		// fullscreen-window
		if (graphicdevice.isFullScreenSupported() && graphicdevice.getFullScreenWindow() != null) {
			// disable fullscreen-mode
			graphicdevice.setFullScreenWindow(null);
			// hide menubar
			jMenuBarDesktop.setVisible(true);
			// make frame resizable again
			mainframe.setResizable(true);
			// dispose frame, so we can restore the decoration
			mainframe.dispose();
			try {
				// set decoration
				mainframe.setUndecorated(false);
			} catch (IllegalComponentStateException e) {
				Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage());
			}
			// show frame again
			mainframe.setVisible(true);
		}
	}

	/**
	 * This method extracts the timestamp-id of the selected node's name.
	 *
	 * @return the timestamp-id of the node's name (userobject) as string, or
	 *         {@code null} if an error occured or nothing was found.
	 */
	private String getSelectedNodeTimestamp() {
		DefaultMutableTreeNode selectednode = (DefaultMutableTreeNode) jTreeDesktop.getLastSelectedPathComponent();
		return (TreeUtil.getNodeTimestamp(selectednode));
	}

	/**
	 * This actions opens an input-dialog where the user cann add comments to the
	 * currently selected node or bullet-point.<br>
	 * <br>
	 * These comments are displayed in a grey area, just like it appears in typical
	 * office-word-programs (word, writer, pages...).<br>
	 * <br>
	 * The comments are added to the xml-file that stores the desktop-data as well
	 * as to a linked list which manages the comments. See
	 * {@link #exportEntriesToEditorPane exportEntriesToEditorPane} for more details
	 * on how the display-page is created.
	 */
	@Action(enabledProperty = "nodeSelected")
	public void commentNode() {
		// get the comment of the selected entry
		String oldcomment = desktopObj.getComment(getSelectedNodeTimestamp(), lineseparator);
		// open an input-dialog, setting the selected value as default-value
		if (null == biggerEditDlg) {
			// create a new dialog with the bigger edit-field, passing some initial values
			biggerEditDlg = new CBiggerEditField(this, settingsObj, resourceMap.getString("newCommentTitle"),
					oldcomment, "", Constants.EDIT_DESKTOP_COMMENT);
			// center window
			biggerEditDlg.setLocationRelativeTo(this);
		}
		// show window
		ZettelkastenApp.getApplication().show(biggerEditDlg);
		// after closing the window, get the new value
		String newcomment = biggerEditDlg.getNewValue();
		// delete the input-dialog
		biggerEditDlg.dispose();
		biggerEditDlg = null;

		if (newcomment != null) {
			// and re-convert all new lines to br's. this is necessary for converting
			// them into <br>'s because the entry is displayed as html-content. simple
			// new lines without "<br>" command would not be shown as new lines
			//
			// but first, we habe to remove all carriage-returns (\r), which are part of the
			// line-seperator in windows. somehow, the replace-command does *not* work, when
			// we replace "System.lineSeparator()" with "[br]", but only when
			// a "\n" is replaced by [br]. So, in case the system's line-separator also
			// contains a
			// "\r", it is replaced by nothing, to clean the content.
			if (lineseparator.contains("\r")) {
				newcomment = newcomment.replace("\r", "");
			}
			newcomment = newcomment.replace("\n", "[br]");
			// set the comment to the selected entry
			if (desktopObj.setComment(getSelectedNodeTimestamp(), newcomment)) {
				// update treeview, so the new comment is also associated with the
				// correct node. we have to do this, because the comments are managed
				// via a linked list that is created in this method. otherwise the
				// comment would not appear...
				updateTreeView();
				// display needs to be updated...
				setNeedsUpdate(true);
			} else {
				// in case the new comment could not be set, tell user about it...
				JOptionPane.showMessageDialog(this, resourceMap.getString("errSetCommentMsg"),
						resourceMap.getString("errSetCommentTitle"), JOptionPane.PLAIN_MESSAGE);
			}
		}
		// if view option was comments only, change this option if we don't have any
		// comments at all
		if (Constants.DESKTOP_ONLY_COMMENTS == settingsObj.getDesktopCommentDisplayOptions()
				&& !desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement())) {
			settingsObj.setDesktopCommentDisplayOptions(Constants.DESKTOP_WITH_COMMENTS);
		}
	}

	/**
	 * @return the background task
	 */
	@Action
	public Task<? extends Object, ? extends Void> displayTask() {
		return new createDisplayTask(
				org.jdesktop.application.Application.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class));
	}

	private class createDisplayTask extends org.jdesktop.application.Task<Object, Void> {

		// create a new stringbuilder that will contain the final string, i.e.
		// the html-page which we set to the jeditorpane
		StringBuilder sbDisplayTask = new StringBuilder();

		createDisplayTask(org.jdesktop.application.Application app) {
			// Runs on the EDT. Copy GUI state that
			// doInBackground() depends on from parameters
			// to createLinksTask fields, here.
			super(app);

			cDisplayTask = this;
		}

		@Override
		protected Object doInBackground() {
			// Your Task's code here. This method runs
			// on a background thread, so don't reference
			// the Swing GUI from here.

			// tell programm that the task is running
			cDisplayTaskIsRunning = true;
			// clear content
			jEditorPaneMain.setText(resourceMap.getString("contentBeingUpdated"));
			// get the treemodel
			DefaultTreeModel dtm = (DefaultTreeModel) jTreeDesktop.getModel();
			// create a new root element from the current desktop name and set it as root
			DefaultMutableTreeNode root = (DefaultMutableTreeNode) dtm.getRoot();
			// check whether the current desktop has any children at all
			if (root.getChildCount() > 0) {
				//
				boolean showComments;
				// clean stringbuilder for word-count
				sbWordCountDisplayTask.setLength(0);
				// create the content for the html-page
				sbDisplayTask.append("<table ");
				if (PlatformUtil.isJava7OnMac() || PlatformUtil.isJava7OnWindows()) {
					sbDisplayTask.append("cellspacing=\"0\" ");
				}
				sbDisplayTask.append("class=\"maintable\">");
				// check which display option is chosen
				switch (settingsObj.getDesktopCommentDisplayOptions()) {
				case Constants.DESKTOP_WITH_COMMENTS:
					showComments = desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement());
					exportEntriesToEditorPane(root, sbDisplayTask, showComments);
					break;
				case Constants.DESKTOP_WITHOUT_COMMENTS:
					showComments = false;
					exportEntriesToEditorPane(root, sbDisplayTask, showComments);
					break;
				case Constants.DESKTOP_ONLY_COMMENTS:
					showComments = false;
					exportCommentsToEditorPane(root, sbDisplayTask);
					break;
				default:
					showComments = desktopObj.desktopHasComments(desktopObj.getCurrentDesktopElement());
					exportEntriesToEditorPane(root, sbDisplayTask, showComments);
					break;
				}
				// retrieve all authors from desktop
				// therefor, we first need all entries
				int[] entries = desktopObj.retrieveDesktopEntries();
				LinkedList<String> remainingAuthors = new LinkedList<>();
				// interate entries
				for (int e : entries) {
					// get authors
					String[] aus = dataObj.getAuthors(e);
					// iterate all authors
					if (aus != null && aus.length > 0) {
						for (String au : aus) {
							// check whether author exists in our array
							if (!remainingAuthors.contains(au)) {
								// if not, add it
								remainingAuthors.add(au);
							}
						}
					}
				}
				// extract footnotes.
				LinkedList<String> footnotes = Tools.extractFootnotesFromContent(sbDisplayTask.toString());
				boolean hasAuthors = (footnotes.size() > 0 || remainingAuthors.size() > 0);
				// check whether we have any footnotes or authors
				if (hasAuthors) {
					// first, init the list in html...
					// create a separator line
					sbDisplayTask.append("<tr>");
					if (showComments) {
						sbDisplayTask.append(lineseparator).append("<td class=\"comment\"></td>");
					}
					sbDisplayTask.append(lineseparator).append("<td><hr></td></tr>").append(lineseparator);
					// add title "references"
					sbDisplayTask.append("<tr>");
					if (showComments) {
						sbDisplayTask.append(lineseparator).append("<td class=\"comment\"></td>");
					}
					sbDisplayTask.append(lineseparator).append("<td><h1>");
					// append a new headline with the bullet's name
					sbDisplayTask.append(resourceMap.getString("referenceListHeading"));
					sbDisplayTask.append("</h1></td></tr>").append(lineseparator);
					// and add another table row for the unordered list...
					sbDisplayTask.append("<tr>");
					if (showComments) {
						sbDisplayTask.append(lineseparator).append("<td class=\"comment\"></td>");
					}
					sbDisplayTask.append(lineseparator).append("<td>").append(lineseparator);
				}
				// now we have all footnotes, i.e. the author-index-numbers, in the linked
				// list. now we can create a reference list
				if (footnotes.size() > 0) {
					// iterator for the linked list
					Iterator<String> i = footnotes.iterator();

					while (i.hasNext()) {
						String au = i.next();
						try {
							int aunr = Integer.parseInt(au);
							String aus = dataObj.getAuthor(aunr);
							sbDisplayTask.append("<p class=\"reflist\"><b>[<a name=\"fn_").append(au).append("\">")
									.append(au).append("</a>]</b> ");
							sbDisplayTask.append(aus);
							sbDisplayTask.append("</p>").append(lineseparator);
							// remove author from remaining list
							remainingAuthors.remove(aus);
						} catch (NumberFormatException e) {
							Constants.zknlogger.log(Level.WARNING, e.getLocalizedMessage());
						}
					}
				}
				// check whether we have any remaining authors that did not appear in footnotes
				if (remainingAuthors.size() > 0) {
					// sort array
					java.util.Collections.sort(remainingAuthors);
					// iterator for the linked list
					Iterator<String> ri = remainingAuthors.iterator();
					while (ri.hasNext()) {
						String aus = ri.next();
						sbDisplayTask.append("<p class=\"reflist\">");
						sbDisplayTask.append(aus);
						sbDisplayTask.append("</p>").append(lineseparator);
					}
				}
				// close tags
				if (hasAuthors) {
					sbDisplayTask.append("</td></tr>").append(lineseparator);
				}
				// and close table tags...
				sbDisplayTask.append("</table>");
				// get complete entry-content, i.e. title and content
				String wordcoutnstring = sbWordCountDisplayTask.toString();
				// split complete content at each word
				String[] words = wordcoutnstring.toLowerCase().replace("ä", "ae").replace("ö", "oe").replace("ü", "ue")
						.replace("ß", "ss").split("\\W");
				// init wordcounter
				int wordcount = 0;
				// iterate all words of the entry
				for (String word : words) {
					// remove all non-letter-chars
					word = word.replace("([^A-Za-z0-9]+)", "");
					// trim spaces
					word = word.trim();
					// if we have a "word" with more than one char, count it as word...
					if (!word.isEmpty() /* && word.length()>1 */) {
						wordcount++;
					}
				}
				// set count words to label
				jLabelWordCount.setText("(" + wordcount + " " + resourceMap.getString("WordCount") + ", "
						+ sbWordCountDisplayTask.length() + " " + resourceMap.getString("CharCount") + ")");
			}
			return null;
		}

		@Override
		protected void succeeded(Object result) {
			// Runs on the EDT. Update the GUI based on
			// the result computed by doInBackground().
			//
			// tell everbody that the display is up to date
			setNeedsUpdate(false);
			// store complete page. we need this string for the live-search,
			// since e.g. German umlauts will be escaped in the jEditorPane, so
			// we can't retrieve the page's content via jEditorPane.getText().
			completePage = sbDisplayTask.toString();
			// if we have any content, insert html-header at the beginning...
			if (sbDisplayTask.length() > 0) {
				sbDisplayTask.insert(0, HtmlUbbUtil.getHtmlHeaderForDesktop(settingsObj, false));
			}
			// set the html-page to the editor pane
			jEditorPaneMain.setText(sbDisplayTask.toString());
			// scroll to first entry
			jEditorPaneMain.setCaretPosition(0);
		}

		@Override
		protected void finished() {
			super.finished();
			cDisplayTaskIsRunning = false;
			cDisplayTask = null;
		}
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	// <editor-fold defaultstate="collapsed" desc="Generated
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPopupMenuDesktop = new javax.swing.JPopupMenu();
        popupNewBullet = new javax.swing.JMenuItem();
        popupNewEntry = new javax.swing.JMenuItem();
        popupNewLuhmann = new javax.swing.JMenuItem();
        jSeparator23 = new javax.swing.JPopupMenu.Separator();
        popupExportBullet = new javax.swing.JMenuItem();
        popupExportBulletToSearch = new javax.swing.JMenuItem();
        jSeparator11 = new javax.swing.JSeparator();
        popupModifyEntry = new javax.swing.JMenuItem();
        popupApplyModificationsEntry = new javax.swing.JMenuItem();
        jSeparator25 = new javax.swing.JSeparator();
        popupCut = new javax.swing.JMenuItem();
        popupCopy = new javax.swing.JMenuItem();
        popupPaste = new javax.swing.JMenuItem();
        jSeparator12 = new javax.swing.JSeparator();
        popupRename = new javax.swing.JMenuItem();
        popupComment = new javax.swing.JMenuItem();
        jSeparator13 = new javax.swing.JSeparator();
        popupDelete = new javax.swing.JMenuItem();
        jSeparator14 = new javax.swing.JSeparator();
        popupShowEntryInMain = new javax.swing.JMenuItem();
        popupRefreshView = new javax.swing.JMenuItem();
        jPopupMenuCutCopyPaste = new javax.swing.JPopupMenu();
        jMenuItemNotesCut = new javax.swing.JMenuItem();
        jMenuItemNotesCopy = new javax.swing.JMenuItem();
        jMenuItemNotesPaste = new javax.swing.JMenuItem();
        buttonGroupDesktopView = new javax.swing.ButtonGroup();
        jToolBarDesktop = new javax.swing.JToolBar();
        tb_newbullet = new javax.swing.JButton();
        tb_newentry = new javax.swing.JButton();
        tb_addluhmann = new javax.swing.JButton();
        jSeparator3 = new javax.swing.JToolBar.Separator();
        tb_modifyentry = new javax.swing.JButton();
        tb_cut = new javax.swing.JButton();
        tb_copy = new javax.swing.JButton();
        tb_paste = new javax.swing.JButton();
        jSeparator4 = new javax.swing.JToolBar.Separator();
        tb_moveup = new javax.swing.JButton();
        tb_movedown = new javax.swing.JButton();
        jSeparator29 = new javax.swing.JToolBar.Separator();
        tb_rename = new javax.swing.JButton();
        tb_comment = new javax.swing.JButton();
        tb_delete = new javax.swing.JButton();
        jSeparator7 = new javax.swing.JToolBar.Separator();
        tb_refresh = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        jSplitPaneDesktop1 = new javax.swing.JSplitPane();
        jPanel3 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTreeDesktop = new javax.swing.JTree();
        jPanel4 = new javax.swing.JPanel();
        jSplitPaneDesktop2 = new javax.swing.JSplitPane();
        jPanel5 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        jEditorPaneMain = new javax.swing.JEditorPane();
        jPanelLiveSearch = new javax.swing.JPanel();
        jTextFieldLiveSearch = new javax.swing.JTextField();
        jButtonLivePrev = new javax.swing.JButton();
        jButtonLiveNext = new javax.swing.JButton();
        jButtonLiveCancel = new javax.swing.JButton();
        jPanel6 = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        jScrollPane4 = new javax.swing.JScrollPane();
        jTextArea2 = new javax.swing.JTextArea();
        jScrollPane5 = new javax.swing.JScrollPane();
        jTextArea3 = new javax.swing.JTextArea();
        jPanel2 = new javax.swing.JPanel();
        jPanel7 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jComboBoxDesktop = new javax.swing.JComboBox();
        statusAnimationLabel = new javax.swing.JLabel();
        jButtonShowMultipleOccurencesDlg = new javax.swing.JButton();
        jLabelWordCount = new javax.swing.JLabel();
        jMenuBarDesktop = new javax.swing.JMenuBar();
        desktopMenuFile = new javax.swing.JMenu();
        newDesktopMenuItem = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        addBulletMenuItem = new javax.swing.JMenuItem();
        insertNewEntryMenuItem = new javax.swing.JMenuItem();
        jSeparator31 = new javax.swing.JPopupMenu.Separator();
        addEntryMenuItem = new javax.swing.JMenuItem();
        addLuhmannMenuItem = new javax.swing.JMenuItem();
        addLuhmannCompleteMenuItem = new javax.swing.JMenuItem();
        jSeparator5 = new javax.swing.JSeparator();
        exportSubMenu = new javax.swing.JMenu();
        exportMenuItem = new javax.swing.JMenuItem();
        jSeparator20 = new javax.swing.JSeparator();
        exportMultipleMenuItem = new javax.swing.JMenuItem();
        jSeparator21 = new javax.swing.JSeparator();
        exportDeskToSearch = new javax.swing.JMenuItem();
        jSeparator22 = new javax.swing.JSeparator();
        exportMissingToSearch = new javax.swing.JMenuItem();
        jSeparator28 = new javax.swing.JSeparator();
        archiveDesktopMenuItem = new javax.swing.JMenuItem();
        importArchivedDesktopMenuItem = new javax.swing.JMenuItem();
        jSeparator15 = new javax.swing.JSeparator();
        printMenuItem = new javax.swing.JMenuItem();
        jSeparator16 = new javax.swing.JPopupMenu.Separator();
        closeMenuItem = new javax.swing.JMenuItem();
        desktopMenuEdit = new javax.swing.JMenu();
        modifyEntryItem = new javax.swing.JMenuItem();
        applyModificationsToOriginalMenuItem = new javax.swing.JMenuItem();
        applyAllModificationsMenuItem = new javax.swing.JMenuItem();
        jSeparator24 = new javax.swing.JSeparator();
        cutMenuItem = new javax.swing.JMenuItem();
        copyMenuItem = new javax.swing.JMenuItem();
        pasteMenuItem = new javax.swing.JMenuItem();
        jSeparator19 = new javax.swing.JSeparator();
        editEntryMenuItem = new javax.swing.JMenuItem();
        jSeparator17 = new javax.swing.JSeparator();
        moveUpMenuItem = new javax.swing.JMenuItem();
        moveDownMenuItem = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JSeparator();
        renameBulletMenuItem = new javax.swing.JMenuItem();
        commentMenuItem = new javax.swing.JMenuItem();
        jSeparator6 = new javax.swing.JSeparator();
        deleteMenuItem = new javax.swing.JMenuItem();
        desktopMenuFind = new javax.swing.JMenu();
        findMenuLiveSearch = new javax.swing.JMenuItem();
        jSeparator18 = new javax.swing.JSeparator();
        findMenuLiveNext = new javax.swing.JMenuItem();
        findMenuLivePrev = new javax.swing.JMenuItem();
        desktopMenuView = new javax.swing.JMenu();
        updateViewMenuItem = new javax.swing.JMenuItem();
        jSeparator9 = new javax.swing.JSeparator();
        jRadioButtonDesktopWithComment = new javax.swing.JRadioButtonMenuItem();
        jRadioButtonDesktopWithoutComments = new javax.swing.JRadioButtonMenuItem();
        jRadioButtonDesktopOnlyComments = new javax.swing.JRadioButtonMenuItem();
        jSeparator8 = new javax.swing.JPopupMenu.Separator();
        headingsVisibleMenuItem = new javax.swing.JCheckBoxMenuItem();
        entryNumberVisibleMenuItem = new javax.swing.JCheckBoxMenuItem();
        luhmannIconVisible = new javax.swing.JCheckBoxMenuItem();
        jSeparator27 = new javax.swing.JSeparator();
        displayItemsMenuItem = new javax.swing.JMenuItem();
        jSeparator10 = new javax.swing.JSeparator();
        viewFullScreenMenuItem = new javax.swing.JMenuItem();
        jSeparator26 = new javax.swing.JPopupMenu.Separator();
        showDesktopTreeEntryNumberMenuItem = new javax.swing.JCheckBoxMenuItem();
        jSeparator30 = new javax.swing.JPopupMenu.Separator();
        toggleNotesVisibility = new javax.swing.JMenuItem();

        jPopupMenuDesktop.setName("jPopupMenuDesktop"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance().getContext().getActionMap(DesktopFrame.class, this);
        popupNewBullet.setAction(actionMap.get("addBullet")); // NOI18N
        popupNewBullet.setName("popupNewBullet"); // NOI18N
        jPopupMenuDesktop.add(popupNewBullet);

        popupNewEntry.setAction(actionMap.get("addEntry")); // NOI18N
        popupNewEntry.setName("popupNewEntry"); // NOI18N
        jPopupMenuDesktop.add(popupNewEntry);

        popupNewLuhmann.setAction(actionMap.get("addLuhmann")); // NOI18N
        popupNewLuhmann.setName("popupNewLuhmann"); // NOI18N
        jPopupMenuDesktop.add(popupNewLuhmann);

        jSeparator23.setName("jSeparator23"); // NOI18N
        jPopupMenuDesktop.add(jSeparator23);

        popupExportBullet.setAction(actionMap.get("exportDesktopBullet")); // NOI18N
        popupExportBullet.setName("popupExportBullet"); // NOI18N
        jPopupMenuDesktop.add(popupExportBullet);

        popupExportBulletToSearch.setAction(actionMap.get("exportBulletToSearch")); // NOI18N
        popupExportBulletToSearch.setName("popupExportBulletToSearch"); // NOI18N
        jPopupMenuDesktop.add(popupExportBulletToSearch);

        jSeparator11.setName("jSeparator11"); // NOI18N
        jPopupMenuDesktop.add(jSeparator11);

        popupModifyEntry.setAction(actionMap.get("modifiyEntry")); // NOI18N
        popupModifyEntry.setName("popupModifyEntry"); // NOI18N
        jPopupMenuDesktop.add(popupModifyEntry);

        popupApplyModificationsEntry.setAction(actionMap.get("applyModificationsToOriginalEntry")); // NOI18N
        popupApplyModificationsEntry.setName("popupApplyModificationsEntry"); // NOI18N
        jPopupMenuDesktop.add(popupApplyModificationsEntry);

        jSeparator25.setName("jSeparator25"); // NOI18N
        jPopupMenuDesktop.add(jSeparator25);

        popupCut.setAction(actionMap.get("cutNode")); // NOI18N
        popupCut.setName("popupCut"); // NOI18N
        jPopupMenuDesktop.add(popupCut);

        popupCopy.setAction(actionMap.get("copyNode")); // NOI18N
        popupCopy.setName("popupCopy"); // NOI18N
        jPopupMenuDesktop.add(popupCopy);

        popupPaste.setAction(actionMap.get("pasteNode")); // NOI18N
        popupPaste.setName("popupPaste"); // NOI18N
        jPopupMenuDesktop.add(popupPaste);

        jSeparator12.setName("jSeparator12"); // NOI18N
        jPopupMenuDesktop.add(jSeparator12);

        popupRename.setAction(actionMap.get("renameBullet")); // NOI18N
        popupRename.setName("popupRename"); // NOI18N
        jPopupMenuDesktop.add(popupRename);

        popupComment.setAction(actionMap.get("commentNode")); // NOI18N
        popupComment.setName("popupComment"); // NOI18N
        jPopupMenuDesktop.add(popupComment);

        jSeparator13.setName("jSeparator13"); // NOI18N
        jPopupMenuDesktop.add(jSeparator13);

        popupDelete.setAction(actionMap.get("deleteNode")); // NOI18N
        popupDelete.setName("popupDelete"); // NOI18N
        jPopupMenuDesktop.add(popupDelete);

        jSeparator14.setName("jSeparator14"); // NOI18N
        jPopupMenuDesktop.add(jSeparator14);

        popupShowEntryInMain.setAction(actionMap.get("displayEntryInMainframe")); // NOI18N
        popupShowEntryInMain.setName("popupShowEntryInMain"); // NOI18N
        jPopupMenuDesktop.add(popupShowEntryInMain);

        popupRefreshView.setAction(actionMap.get("updateView")); // NOI18N
        popupRefreshView.setName("popupRefreshView"); // NOI18N
        jPopupMenuDesktop.add(popupRefreshView);

        jPopupMenuCutCopyPaste.setName("jPopupMenuCutCopyPaste"); // NOI18N

        jMenuItemNotesCut.setAction(actionMap.get("cut"));
        jMenuItemNotesCut.setName("jMenuItemNotesCut"); // NOI18N
        jPopupMenuCutCopyPaste.add(jMenuItemNotesCut);

        jMenuItemNotesCopy.setAction(actionMap.get("copy"));
        jMenuItemNotesCopy.setName("jMenuItemNotesCopy"); // NOI18N
        jPopupMenuCutCopyPaste.add(jMenuItemNotesCopy);

        jMenuItemNotesPaste.setAction(actionMap.get("paste"));
        jMenuItemNotesPaste.setName("jMenuItemNotesPaste"); // NOI18N
        jPopupMenuCutCopyPaste.add(jMenuItemNotesPaste);

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance().getContext().getResourceMap(DesktopFrame.class);
        setTitle(resourceMap.getString("FormDesktop.title")); // NOI18N
        setMinimumSize(new java.awt.Dimension(350, 250));
        setName("FormDesktop"); // NOI18N

        jToolBarDesktop.setBorder(javax.swing.BorderFactory.createMatteBorder(0, 0, 1, 0, resourceMap.getColor("jToolBarDesktop.border.matteColor"))); // NOI18N
        jToolBarDesktop.setRollover(true);
        jToolBarDesktop.setMinimumSize(new java.awt.Dimension(200, 10));
        jToolBarDesktop.setName("jToolBarDesktop"); // NOI18N

        tb_newbullet.setAction(actionMap.get("addBullet")); // NOI18N
        tb_newbullet.setText(resourceMap.getString("tb_newbullet.text")); // NOI18N
        tb_newbullet.setBorderPainted(false);
        tb_newbullet.setFocusPainted(false);
        tb_newbullet.setFocusable(false);
        tb_newbullet.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_newbullet.setName("tb_newbullet"); // NOI18N
        tb_newbullet.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_newbullet);

        tb_newentry.setAction(actionMap.get("addEntry")); // NOI18N
        tb_newentry.setText(resourceMap.getString("tb_newentry.text")); // NOI18N
        tb_newentry.setBorderPainted(false);
        tb_newentry.setFocusPainted(false);
        tb_newentry.setFocusable(false);
        tb_newentry.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_newentry.setName("tb_newentry"); // NOI18N
        tb_newentry.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_newentry);

        tb_addluhmann.setAction(actionMap.get("addLuhmann")); // NOI18N
        tb_addluhmann.setText(resourceMap.getString("tb_addluhmann.text")); // NOI18N
        tb_addluhmann.setBorderPainted(false);
        tb_addluhmann.setFocusPainted(false);
        tb_addluhmann.setFocusable(false);
        tb_addluhmann.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_addluhmann.setName("tb_addluhmann"); // NOI18N
        tb_addluhmann.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_addluhmann);

        jSeparator3.setName("jSeparator3"); // NOI18N
        jToolBarDesktop.add(jSeparator3);

        tb_modifyentry.setAction(actionMap.get("modifiyEntry")); // NOI18N
        tb_modifyentry.setText(resourceMap.getString("tb_modifyentry.text")); // NOI18N
        tb_modifyentry.setBorderPainted(false);
        tb_modifyentry.setFocusPainted(false);
        tb_modifyentry.setFocusable(false);
        tb_modifyentry.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_modifyentry.setName("tb_modifyentry"); // NOI18N
        tb_modifyentry.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_modifyentry);

        tb_cut.setAction(actionMap.get("cutNode")); // NOI18N
        tb_cut.setText(resourceMap.getString("tb_cut.text")); // NOI18N
        tb_cut.setBorderPainted(false);
        tb_cut.setFocusPainted(false);
        tb_cut.setFocusable(false);
        tb_cut.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_cut.setName("tb_cut"); // NOI18N
        tb_cut.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_cut);

        tb_copy.setAction(actionMap.get("copyNode")); // NOI18N
        tb_copy.setText(resourceMap.getString("tb_copy.text")); // NOI18N
        tb_copy.setBorderPainted(false);
        tb_copy.setFocusPainted(false);
        tb_copy.setFocusable(false);
        tb_copy.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_copy.setName("tb_copy"); // NOI18N
        tb_copy.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_copy);

        tb_paste.setAction(actionMap.get("pasteNode")); // NOI18N
        tb_paste.setText(resourceMap.getString("tb_paste.text")); // NOI18N
        tb_paste.setBorderPainted(false);
        tb_paste.setFocusPainted(false);
        tb_paste.setFocusable(false);
        tb_paste.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_paste.setName("tb_paste"); // NOI18N
        tb_paste.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_paste);

        jSeparator4.setName("jSeparator4"); // NOI18N
        jToolBarDesktop.add(jSeparator4);

        tb_moveup.setAction(actionMap.get("moveNodeUp")); // NOI18N
        tb_moveup.setText(resourceMap.getString("tb_moveup.text")); // NOI18N
        tb_moveup.setBorderPainted(false);
        tb_moveup.setFocusPainted(false);
        tb_moveup.setFocusable(false);
        tb_moveup.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_moveup.setName("tb_moveup"); // NOI18N
        tb_moveup.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_moveup);

        tb_movedown.setAction(actionMap.get("moveNodeDown")); // NOI18N
        tb_movedown.setText(resourceMap.getString("tb_movedown.text")); // NOI18N
        tb_movedown.setBorderPainted(false);
        tb_movedown.setFocusPainted(false);
        tb_movedown.setFocusable(false);
        tb_movedown.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_movedown.setName("tb_movedown"); // NOI18N
        tb_movedown.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_movedown);

        jSeparator29.setName("jSeparator29"); // NOI18N
        jToolBarDesktop.add(jSeparator29);

        tb_rename.setAction(actionMap.get("renameBullet")); // NOI18N
        tb_rename.setText(resourceMap.getString("tb_rename.text")); // NOI18N
        tb_rename.setBorderPainted(false);
        tb_rename.setFocusPainted(false);
        tb_rename.setFocusable(false);
        tb_rename.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_rename.setName("tb_rename"); // NOI18N
        tb_rename.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_rename);

        tb_comment.setAction(actionMap.get("commentNode")); // NOI18N
        tb_comment.setText(resourceMap.getString("tb_comment.text")); // NOI18N
        tb_comment.setBorderPainted(false);
        tb_comment.setFocusPainted(false);
        tb_comment.setFocusable(false);
        tb_comment.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_comment.setName("tb_comment"); // NOI18N
        tb_comment.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_comment);

        tb_delete.setAction(actionMap.get("deleteNode")); // NOI18N
        tb_delete.setText(resourceMap.getString("tb_delete.text")); // NOI18N
        tb_delete.setBorderPainted(false);
        tb_delete.setFocusPainted(false);
        tb_delete.setFocusable(false);
        tb_delete.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_delete.setName("tb_delete"); // NOI18N
        tb_delete.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_delete);

        jSeparator7.setName("jSeparator7"); // NOI18N
        jToolBarDesktop.add(jSeparator7);

        tb_refresh.setAction(actionMap.get("updateView")); // NOI18N
        tb_refresh.setText(resourceMap.getString("tb_refresh.text")); // NOI18N
        tb_refresh.setBorderPainted(false);
        tb_refresh.setFocusPainted(false);
        tb_refresh.setFocusable(false);
        tb_refresh.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        tb_refresh.setName("tb_refresh"); // NOI18N
        tb_refresh.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBarDesktop.add(tb_refresh);

        jPanel1.setMinimumSize(new java.awt.Dimension(200, 150));
        jPanel1.setName("jPanel1"); // NOI18N
        jPanel1.setLayout(new java.awt.BorderLayout());

        jSplitPaneDesktop1.setDividerLocation(200);
        jSplitPaneDesktop1.setMinimumSize(new java.awt.Dimension(200, 200));
        jSplitPaneDesktop1.setName("jSplitPaneDesktop1"); // NOI18N
        jSplitPaneDesktop1.setOneTouchExpandable(true);

        jPanel3.setMinimumSize(new java.awt.Dimension(50, 100));
        jPanel3.setName("jPanel3"); // NOI18N

        jScrollPane1.setBorder(null);
        jScrollPane1.setMinimumSize(new java.awt.Dimension(20, 20));
        jScrollPane1.setName("jScrollPane1"); // NOI18N

        jTreeDesktop.setName("jTreeDesktop"); // NOI18N
        jScrollPane1.setViewportView(jTreeDesktop);

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 451, Short.MAX_VALUE)
        );

        jSplitPaneDesktop1.setLeftComponent(jPanel3);

        jPanel4.setMinimumSize(new java.awt.Dimension(150, 100));
        jPanel4.setName("jPanel4"); // NOI18N

        jSplitPaneDesktop2.setDividerLocation(400);
        jSplitPaneDesktop2.setMinimumSize(new java.awt.Dimension(150, 150));
        jSplitPaneDesktop2.setName("jSplitPaneDesktop2"); // NOI18N
        jSplitPaneDesktop2.setOneTouchExpandable(true);

        jPanel5.setMinimumSize(new java.awt.Dimension(50, 50));
        jPanel5.setName("jPanel5"); // NOI18N

        jScrollPane2.setBorder(null);
        jScrollPane2.setMinimumSize(new java.awt.Dimension(20, 20));
        jScrollPane2.setName("jScrollPane2"); // NOI18N

        jEditorPaneMain.setEditable(false);
        jEditorPaneMain.setContentType(resourceMap.getString("jEditorPaneMain.contentType")); // NOI18N
        jEditorPaneMain.setText(resourceMap.getString("jEditorPaneMain.text")); // NOI18N
        jEditorPaneMain.setName("jEditorPaneMain"); // NOI18N
        jScrollPane2.setViewportView(jEditorPaneMain);

        jPanelLiveSearch.setMinimumSize(new java.awt.Dimension(20, 20));
        jPanelLiveSearch.setName("jPanelLiveSearch"); // NOI18N

        jTextFieldLiveSearch.setToolTipText(resourceMap.getString("jTextFieldLiveSearch.toolTipText")); // NOI18N
        jTextFieldLiveSearch.setName("jTextFieldLiveSearch"); // NOI18N

        jButtonLivePrev.setAction(actionMap.get("findLivePrev")); // NOI18N
        jButtonLivePrev.setText(resourceMap.getString("jButtonLivePrev.text")); // NOI18N
        jButtonLivePrev.setBorderPainted(false);
        jButtonLivePrev.setContentAreaFilled(false);
        jButtonLivePrev.setFocusPainted(false);
        jButtonLivePrev.setName("jButtonLivePrev"); // NOI18N

        jButtonLiveNext.setAction(actionMap.get("findLiveNext")); // NOI18N
        jButtonLiveNext.setText(resourceMap.getString("jButtonLiveNext.text")); // NOI18N
        jButtonLiveNext.setBorderPainted(false);
        jButtonLiveNext.setContentAreaFilled(false);
        jButtonLiveNext.setFocusPainted(false);
        jButtonLiveNext.setName("jButtonLiveNext"); // NOI18N

        jButtonLiveCancel.setAction(actionMap.get("findCancel")); // NOI18N
        jButtonLiveCancel.setBorderPainted(false);
        jButtonLiveCancel.setContentAreaFilled(false);
        jButtonLiveCancel.setFocusPainted(false);
        jButtonLiveCancel.setName("jButtonLiveCancel"); // NOI18N

        javax.swing.GroupLayout jPanelLiveSearchLayout = new javax.swing.GroupLayout(jPanelLiveSearch);
        jPanelLiveSearch.setLayout(jPanelLiveSearchLayout);
        jPanelLiveSearchLayout.setHorizontalGroup(
            jPanelLiveSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelLiveSearchLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTextFieldLiveSearch)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButtonLivePrev, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButtonLiveNext, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButtonLiveCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        jPanelLiveSearchLayout.setVerticalGroup(
            jPanelLiveSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelLiveSearchLayout.createSequentialGroup()
                .addGap(3, 3, 3)
                .addGroup(jPanelLiveSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButtonLiveCancel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jButtonLiveNext, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jButtonLivePrev, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jTextFieldLiveSearch, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanelLiveSearch, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup()
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGap(0, 0, 0)
                .addComponent(jPanelLiveSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        jSplitPaneDesktop2.setLeftComponent(jPanel5);

        jPanel6.setMinimumSize(new java.awt.Dimension(50, 50));
        jPanel6.setName("jPanel6"); // NOI18N

        jScrollPane3.setBorder(null);
        jScrollPane3.setName("jScrollPane3"); // NOI18N

        jTextArea1.setLineWrap(true);
        jTextArea1.setWrapStyleWord(true);
        jTextArea1.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jTextArea1.border.title"))); // NOI18N
        jTextArea1.setName("jTextArea1"); // NOI18N
        jScrollPane3.setViewportView(jTextArea1);

        jScrollPane4.setBorder(null);
        jScrollPane4.setName("jScrollPane4"); // NOI18N

        jTextArea2.setLineWrap(true);
        jTextArea2.setToolTipText(resourceMap.getString("jTextArea2.toolTipText")); // NOI18N
        jTextArea2.setWrapStyleWord(true);
        jTextArea2.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jTextArea2.border.title"))); // NOI18N
        jTextArea2.setName("jTextArea2"); // NOI18N
        jScrollPane4.setViewportView(jTextArea2);

        jScrollPane5.setBorder(null);
        jScrollPane5.setName("jScrollPane5"); // NOI18N

        jTextArea3.setLineWrap(true);
        jTextArea3.setWrapStyleWord(true);
        jTextArea3.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jTextArea3.border.title"))); // NOI18N
        jTextArea3.setName("jTextArea3"); // NOI18N
        jScrollPane5.setViewportView(jTextArea3);

        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
        jPanel6.setLayout(jPanel6Layout);
        jPanel6Layout.setHorizontalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane4, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 50, Short.MAX_VALUE)
            .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 50, Short.MAX_VALUE)
            .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 50, Short.MAX_VALUE)
        );
        jPanel6Layout.setVerticalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 144, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 153, Short.MAX_VALUE))
        );

        jSplitPaneDesktop2.setRightComponent(jPanel6);

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSplitPaneDesktop2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSplitPaneDesktop2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        jSplitPaneDesktop1.setRightComponent(jPanel4);

        jPanel1.add(jSplitPaneDesktop1, java.awt.BorderLayout.CENTER);

        jPanel2.setBorder(javax.swing.BorderFactory.createMatteBorder(1, 0, 0, 0, resourceMap.getColor("jPanel2.border.matteColor"))); // NOI18N
        jPanel2.setMinimumSize(new java.awt.Dimension(200, 30));
        jPanel2.setName("jPanel2"); // NOI18N

        jPanel7.setMinimumSize(new java.awt.Dimension(200, 20));
        jPanel7.setName("jPanel7"); // NOI18N

        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N

        jComboBoxDesktop.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        jComboBoxDesktop.setName("jComboBoxDesktop"); // NOI18N

        statusAnimationLabel.setIcon(resourceMap.getIcon("statusAnimationLabel.icon")); // NOI18N
        statusAnimationLabel.setText(resourceMap.getString("statusAnimationLabel.text")); // NOI18N
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        jButtonShowMultipleOccurencesDlg.setAction(actionMap.get("openMultipleOccurencesMessageDlg")); // NOI18N
        jButtonShowMultipleOccurencesDlg.setIcon(resourceMap.getIcon("jButtonShowMultipleOccurencesDlg.icon")); // NOI18N
        jButtonShowMultipleOccurencesDlg.setToolTipText(resourceMap.getString("jButtonShowMultipleOccurencesDlg.toolTipText")); // NOI18N
        jButtonShowMultipleOccurencesDlg.setBorderPainted(false);
        jButtonShowMultipleOccurencesDlg.setContentAreaFilled(false);
        jButtonShowMultipleOccurencesDlg.setFocusPainted(false);
        jButtonShowMultipleOccurencesDlg.setIconTextGap(0);
        jButtonShowMultipleOccurencesDlg.setName("jButtonShowMultipleOccurencesDlg"); // NOI18N

        jLabelWordCount.setToolTipText(resourceMap.getString("jLabelWordCount.toolTipText")); // NOI18N
        jLabelWordCount.setName("jLabelWordCount"); // NOI18N

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jComboBoxDesktop, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabelWordCount)
                .addGap(18, 18, 18)
                .addComponent(jButtonShowMultipleOccurencesDlg)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addGap(3, 3, 3)
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanel7Layout.createSequentialGroup()
                        .addGap(1, 1, 1)
                        .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel1)
                            .addComponent(jComboBoxDesktop, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabelWordCount)))
                    .addComponent(jButtonShowMultipleOccurencesDlg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(statusAnimationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGap(0, 0, 0)
                .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, 0))
        );

        jMenuBarDesktop.setMinimumSize(new java.awt.Dimension(100, 1));
        jMenuBarDesktop.setName("jMenuBarDesktop"); // NOI18N

        desktopMenuFile.setText(resourceMap.getString("desktopMenuFile.text")); // NOI18N
        desktopMenuFile.setName("desktopMenuFile"); // NOI18N

        newDesktopMenuItem.setAction(actionMap.get("newDesktop")); // NOI18N
        newDesktopMenuItem.setName("newDesktopMenuItem"); // NOI18N
        desktopMenuFile.add(newDesktopMenuItem);

        jSeparator1.setName("jSeparator1"); // NOI18N
        desktopMenuFile.add(jSeparator1);

        addBulletMenuItem.setAction(actionMap.get("addBullet")); // NOI18N
        addBulletMenuItem.setName("addBulletMenuItem"); // NOI18N
        desktopMenuFile.add(addBulletMenuItem);

        insertNewEntryMenuItem.setAction(actionMap.get("insertEntry")); // NOI18N
        insertNewEntryMenuItem.setName("insertNewEntryMenuItem"); // NOI18N
        desktopMenuFile.add(insertNewEntryMenuItem);

        jSeparator31.setName("jSeparator31"); // NOI18N
        desktopMenuFile.add(jSeparator31);

        addEntryMenuItem.setAction(actionMap.get("addEntry")); // NOI18N
        addEntryMenuItem.setName("addEntryMenuItem"); // NOI18N
        desktopMenuFile.add(addEntryMenuItem);

        addLuhmannMenuItem.setAction(actionMap.get("addLuhmann")); // NOI18N
        addLuhmannMenuItem.setName("addLuhmannMenuItem"); // NOI18N
        desktopMenuFile.add(addLuhmannMenuItem);

        addLuhmannCompleteMenuItem.setAction(actionMap.get("addLuhmannComplete")); // NOI18N
        addLuhmannCompleteMenuItem.setName("addLuhmannCompleteMenuItem"); // NOI18N
        desktopMenuFile.add(addLuhmannCompleteMenuItem);

        jSeparator5.setName("jSeparator5"); // NOI18N
        desktopMenuFile.add(jSeparator5);

        exportSubMenu.setText(resourceMap.getString("exportSubMenu.text")); // NOI18N
        exportSubMenu.setName("exportSubMenu"); // NOI18N

        exportMenuItem.setAction(actionMap.get("exportDesktop")); // NOI18N
        exportMenuItem.setName("exportMenuItem"); // NOI18N
        exportSubMenu.add(exportMenuItem);

        jSeparator20.setName("jSeparator20"); // NOI18N
        exportSubMenu.add(jSeparator20);

        exportMultipleMenuItem.setAction(actionMap.get("exportMultipleDesktop")); // NOI18N
        exportMultipleMenuItem.setName("exportMultipleMenuItem"); // NOI18N
        exportSubMenu.add(exportMultipleMenuItem);

        jSeparator21.setName("jSeparator21"); // NOI18N
        exportSubMenu.add(jSeparator21);

        exportDeskToSearch.setAction(actionMap.get("exportToSearch")); // NOI18N
        exportDeskToSearch.setName("exportDeskToSearch"); // NOI18N
        exportSubMenu.add(exportDeskToSearch);

        jSeparator22.setName("jSeparator22"); // NOI18N
        exportSubMenu.add(jSeparator22);

        exportMissingToSearch.setAction(actionMap.get("exportMissingToSearch")); // NOI18N
        exportMissingToSearch.setName("exportMissingToSearch"); // NOI18N
        exportSubMenu.add(exportMissingToSearch);

        desktopMenuFile.add(exportSubMenu);

        jSeparator28.setName("jSeparator28"); // NOI18N
        desktopMenuFile.add(jSeparator28);

        archiveDesktopMenuItem.setAction(actionMap.get("archiveDesktop")); // NOI18N
        archiveDesktopMenuItem.setName("archiveDesktopMenuItem"); // NOI18N
        desktopMenuFile.add(archiveDesktopMenuItem);

        importArchivedDesktopMenuItem.setAction(actionMap.get("importArchivedDesktop")); // NOI18N
        importArchivedDesktopMenuItem.setName("importArchivedDesktopMenuItem"); // NOI18N
        desktopMenuFile.add(importArchivedDesktopMenuItem);

        jSeparator15.setName("jSeparator15"); // NOI18N
        desktopMenuFile.add(jSeparator15);

        printMenuItem.setAction(actionMap.get("printContent")); // NOI18N
        printMenuItem.setName("printMenuItem"); // NOI18N
        desktopMenuFile.add(printMenuItem);

        jSeparator16.setName("jSeparator16"); // NOI18N
        desktopMenuFile.add(jSeparator16);

        closeMenuItem.setAction(actionMap.get("closeWindow")); // NOI18N
        closeMenuItem.setName("closeMenuItem"); // NOI18N
        desktopMenuFile.add(closeMenuItem);

        jMenuBarDesktop.add(desktopMenuFile);

        desktopMenuEdit.setText(resourceMap.getString("desktopMenuEdit.text")); // NOI18N
        desktopMenuEdit.setName("desktopMenuEdit"); // NOI18N

        modifyEntryItem.setAction(actionMap.get("modifiyEntry")); // NOI18N
        modifyEntryItem.setName("modifyEntryItem"); // NOI18N
        desktopMenuEdit.add(modifyEntryItem);

        applyModificationsToOriginalMenuItem.setAction(actionMap.get("applyModificationsToOriginalEntry")); // NOI18N
        applyModificationsToOriginalMenuItem.setName("applyModificationsToOriginalMenuItem"); // NOI18N
        desktopMenuEdit.add(applyModificationsToOriginalMenuItem);

        applyAllModificationsMenuItem.setAction(actionMap.get("applyAllModificationsToOriginalEntries")); // NOI18N
        applyAllModificationsMenuItem.setName("applyAllModificationsMenuItem"); // NOI18N
        desktopMenuEdit.add(applyAllModificationsMenuItem);

        jSeparator24.setName("jSeparator24"); // NOI18N
        desktopMenuEdit.add(jSeparator24);

        cutMenuItem.setAction(actionMap.get("cutNode")); // NOI18N
        cutMenuItem.setName("cutMenuItem"); // NOI18N
        desktopMenuEdit.add(cutMenuItem);

        copyMenuItem.setAction(actionMap.get("copyNode")); // NOI18N
        copyMenuItem.setName("copyMenuItem"); // NOI18N
        desktopMenuEdit.add(copyMenuItem);

        pasteMenuItem.setAction(actionMap.get("pasteNode")); // NOI18N
        pasteMenuItem.setName("pasteMenuItem"); // NOI18N
        desktopMenuEdit.add(pasteMenuItem);

        jSeparator19.setName("jSeparator19"); // NOI18N
        desktopMenuEdit.add(jSeparator19);

        editEntryMenuItem.setAction(actionMap.get("editEntry")); // NOI18N
        editEntryMenuItem.setName("editEntryMenuItem"); // NOI18N
        desktopMenuEdit.add(editEntryMenuItem);

        jSeparator17.setName("jSeparator17"); // NOI18N
        desktopMenuEdit.add(jSeparator17);

        moveUpMenuItem.setAction(actionMap.get("moveNodeUp")); // NOI18N
        moveUpMenuItem.setName("moveUpMenuItem"); // NOI18N
        desktopMenuEdit.add(moveUpMenuItem);

        moveDownMenuItem.setAction(actionMap.get("moveNodeDown")); // NOI18N
        moveDownMenuItem.setName("moveDownMenuItem"); // NOI18N
        desktopMenuEdit.add(moveDownMenuItem);

        jSeparator2.setName("jSeparator2"); // NOI18N
        desktopMenuEdit.add(jSeparator2);

        renameBulletMenuItem.setAction(actionMap.get("renameBullet")); // NOI18N
        renameBulletMenuItem.setName("renameBulletMenuItem"); // NOI18N
        desktopMenuEdit.add(renameBulletMenuItem);

        commentMenuItem.setAction(actionMap.get("commentNode")); // NOI18N
        commentMenuItem.setName("commentMenuItem"); // NOI18N
        desktopMenuEdit.add(commentMenuItem);

        jSeparator6.setName("jSeparator6"); // NOI18N
        desktopMenuEdit.add(jSeparator6);

        deleteMenuItem.setAction(actionMap.get("deleteNode")); // NOI18N
        deleteMenuItem.setName("deleteMenuItem"); // NOI18N
        desktopMenuEdit.add(deleteMenuItem);

        jMenuBarDesktop.add(desktopMenuEdit);

        desktopMenuFind.setText(resourceMap.getString("desktopMenuFind.text")); // NOI18N
        desktopMenuFind.setName("desktopMenuFind"); // NOI18N

        findMenuLiveSearch.setAction(actionMap.get("findLive")); // NOI18N
        findMenuLiveSearch.setName("findMenuLiveSearch"); // NOI18N
        desktopMenuFind.add(findMenuLiveSearch);

        jSeparator18.setName("jSeparator18"); // NOI18N
        desktopMenuFind.add(jSeparator18);

        findMenuLiveNext.setAction(actionMap.get("findLiveNext")); // NOI18N
        findMenuLiveNext.setName("findMenuLiveNext"); // NOI18N
        desktopMenuFind.add(findMenuLiveNext);

        findMenuLivePrev.setAction(actionMap.get("findLivePrev")); // NOI18N
        findMenuLivePrev.setName("findMenuLivePrev"); // NOI18N
        desktopMenuFind.add(findMenuLivePrev);

        jMenuBarDesktop.add(desktopMenuFind);

        desktopMenuView.setText(resourceMap.getString("desktopMenuView.text")); // NOI18N
        desktopMenuView.setName("desktopMenuView"); // NOI18N

        updateViewMenuItem.setAction(actionMap.get("updateView")); // NOI18N
        updateViewMenuItem.setName("updateViewMenuItem"); // NOI18N
        desktopMenuView.add(updateViewMenuItem);

        jSeparator9.setName("jSeparator9"); // NOI18N
        desktopMenuView.add(jSeparator9);

        jRadioButtonDesktopWithComment.setAction(actionMap.get("menuDisplayDesktopWithComments")); // NOI18N
        buttonGroupDesktopView.add(jRadioButtonDesktopWithComment);
        jRadioButtonDesktopWithComment.setName("jRadioButtonDesktopWithComment"); // NOI18N
        desktopMenuView.add(jRadioButtonDesktopWithComment);

        jRadioButtonDesktopWithoutComments.setAction(actionMap.get("menuDisplayDesktopWithoutComments")); // NOI18N
        buttonGroupDesktopView.add(jRadioButtonDesktopWithoutComments);
        jRadioButtonDesktopWithoutComments.setName("jRadioButtonDesktopWithoutComments"); // NOI18N
        desktopMenuView.add(jRadioButtonDesktopWithoutComments);

        jRadioButtonDesktopOnlyComments.setAction(actionMap.get("menuDisplayDesktopOnlyComments")); // NOI18N
        buttonGroupDesktopView.add(jRadioButtonDesktopOnlyComments);
        jRadioButtonDesktopOnlyComments.setName("jRadioButtonDesktopOnlyComments"); // NOI18N
        desktopMenuView.add(jRadioButtonDesktopOnlyComments);

        jSeparator8.setName("jSeparator8"); // NOI18N
        desktopMenuView.add(jSeparator8);

        headingsVisibleMenuItem.setAction(actionMap.get("switchHeadingsVisibility")); // NOI18N
        headingsVisibleMenuItem.setSelected(true);
        headingsVisibleMenuItem.setName("headingsVisibleMenuItem"); // NOI18N
        desktopMenuView.add(headingsVisibleMenuItem);

        entryNumberVisibleMenuItem.setAction(actionMap.get("switchEntryNumberVisibility")); // NOI18N
        entryNumberVisibleMenuItem.setSelected(true);
        entryNumberVisibleMenuItem.setName("entryNumberVisibleMenuItem"); // NOI18N
        desktopMenuView.add(entryNumberVisibleMenuItem);

        luhmannIconVisible.setAction(actionMap.get("switchLuhmannVisibility")); // NOI18N
        luhmannIconVisible.setSelected(true);
        luhmannIconVisible.setName("luhmannIconVisible"); // NOI18N
        desktopMenuView.add(luhmannIconVisible);

        jSeparator27.setName("jSeparator27"); // NOI18N
        desktopMenuView.add(jSeparator27);

        displayItemsMenuItem.setAction(actionMap.get("displayItems")); // NOI18N
        displayItemsMenuItem.setName("displayItemsMenuItem"); // NOI18N
        desktopMenuView.add(displayItemsMenuItem);

        jSeparator10.setName("jSeparator10"); // NOI18N
        desktopMenuView.add(jSeparator10);

        viewFullScreenMenuItem.setAction(actionMap.get("viewFullScreen")); // NOI18N
        viewFullScreenMenuItem.setName("viewFullScreenMenuItem"); // NOI18N
        desktopMenuView.add(viewFullScreenMenuItem);

        jSeparator26.setName("jSeparator26"); // NOI18N
        desktopMenuView.add(jSeparator26);

        showDesktopTreeEntryNumberMenuItem.setAction(actionMap.get("showDesktopEntryNumber")); // NOI18N
        showDesktopTreeEntryNumberMenuItem.setSelected(true);
        showDesktopTreeEntryNumberMenuItem.setName("showDesktopTreeEntryNumberMenuItem"); // NOI18N
        desktopMenuView.add(showDesktopTreeEntryNumberMenuItem);

        jSeparator30.setName("jSeparator30"); // NOI18N
        desktopMenuView.add(jSeparator30);

        toggleNotesVisibility.setAction(actionMap.get("toggleNotesVisibility")); // NOI18N
        toggleNotesVisibility.setName("toggleNotesVisibility"); // NOI18N
        desktopMenuView.add(toggleNotesVisibility);

        jMenuBarDesktop.add(desktopMenuView);

        setJMenuBar(jMenuBarDesktop);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jToolBarDesktop, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jToolBarDesktop, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, 0)
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGap(0, 0, 0)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	/**
	 * This variable indicates whether the selection in the jtree is a bullet-point
	 * or not, and no root-element
	 */
	private boolean bulletSelected = false;

	/**
	 * This variable indicates whether the selection in the jtree is a bullet-point
	 * or not, and no root-element
	 *
	 * @return Returns true, if a bullet-point (except root element) is selected in
	 *         the tree view.
	 */
	public boolean isBulletSelected() {
		return bulletSelected;
	}

	/**
	 * This variable indicates whether the selection in the jtree is a bullet-point
	 * or not, and no root-element. Triggers a property change to (de-)activate menu
	 * items.
	 *
	 * @param b true, if a bullet point is selected.
	 */
	public void setBulletSelected(boolean b) {
		boolean old = isBulletSelected();
		this.bulletSelected = b;
		firePropertyChange("bulletSelected", old, isBulletSelected());
	}

	/**
	 * This variable indicates whether the selection in the jtree is a child-note
	 * (entry), i.e. no bullet and no root-element
	 */
	private boolean entryNodeSelected = false;

	/**
	 * This variable indicates whether the selection in the jtree is a child-note
	 * (entry), i.e. no bullet and no root-element
	 *
	 * @return
	 */
	public boolean isEntryNodeSelected() {
		return entryNodeSelected;
	}

	/**
	 * This variable indicates whether the selection in the jtree is a child-note
	 * (entry), i.e. no bullet and no root-element. Triggers a property change to
	 * (de-)activate menu items.
	 *
	 * @param b
	 */
	public void setEntryNodeSelected(boolean b) {
		boolean old = isEntryNodeSelected();
		this.entryNodeSelected = b;
		firePropertyChange("entryNodeSelected", old, isEntryNodeSelected());
	}

	/**
	 * This variable indicates whether the selection in the jtree is a child-note
	 * (entry), i.e. no bullet and no root-element
	 */
	private boolean nodeSelected = false;

	/**
	 * This variable indicates whether the selection in the jtree is a child-note
	 * (entry), i.e. no bullet and no root-element
	 *
	 * @return
	 */
	public boolean isNodeSelected() {
		return nodeSelected;
	}

	/**
	 * This variable indicates whether the selection in the jtree is a child-note
	 * (entry), i.e. no bullet and no root-element
	 *
	 * @param b
	 */
	public void setNodeSelected(boolean b) {
		boolean old = isNodeSelected();
		this.nodeSelected = b;
		firePropertyChange("nodeSelected", old, isNodeSelected());
	}

	/**
	 * This variable indicates whether the we have any selection in the jtree, i.e.
	 * a bullet, a child-node or a root-element
	 */
	private boolean anyNodeSelected = false;

	/**
	 * This variable indicates whether the we have any selection in the jtree, i.e.
	 * a bullet, a child-node or a root-element
	 *
	 * @return
	 */
	public boolean isAnyNodeSelected() {
		return anyNodeSelected;
	}

	/**
	 * This variable indicates whether the we have any selection in the jtree, i.e.
	 * a bullet, a child-node or a root-element
	 *
	 * @param b
	 */
	public void setAnyNodeSelected(boolean b) {
		boolean old = isAnyNodeSelected();
		this.anyNodeSelected = b;
		firePropertyChange("anyNodeSelected", old, isAnyNodeSelected());
	}

	/**
	 * This variable indicates whether the selected entry was modified or not.
	 */
	private boolean modifiedEntryNode = false;

	/**
	 * This variable indicates whether the selected entry was modified or not.
	 *
	 * @return
	 */
	public boolean isModifiedEntryNode() {
		return modifiedEntryNode;
	}

	/**
	 * This variable indicates whether the selected entry was modified or not.
	 *
	 * @param b
	 */
	public void setModifiedEntryNode(boolean b) {
		boolean old = isModifiedEntryNode();
		this.modifiedEntryNode = b;
		firePropertyChange("modifiedEntryNode", old, isModifiedEntryNode());
	}

	/**
	 * This variable indicates whether the selected node is a child-note (entry) and
	 * also has luhmann-numbers (followers)
	 */
	private boolean luhmannNodeSelected = false;

	/**
	 * This variable indicates whether the selected node is a child-note (entry) and
	 * also has luhmann-numbers (followers)
	 *
	 * @return
	 */
	public boolean isLuhmannNodeSelected() {
		return luhmannNodeSelected;
	}

	/**
	 * This variable indicates whether the selected node is a child-note (entry) and
	 * also has luhmann-numbers (followers)
	 *
	 * @param b
	 */
	public void setLuhmannNodeSelected(boolean b) {
		boolean old = isLuhmannNodeSelected();
		this.luhmannNodeSelected = b;
		firePropertyChange("luhmannNodeSelected", old, isLuhmannNodeSelected());
	}

	/**
	 * This variable indicates whether we have any entries or bullets in the
	 * clipboard
	 */
	private boolean clipFilled = false;

	/**
	 * This variable indicates whether we have any entries or bullets in the
	 * clipboard
	 *
	 * @return
	 */
	public boolean isClipFilled() {
		return clipFilled;
	}

	/**
	 * This variable indicates whether we have any entries or bullets in the
	 * clipboard
	 *
	 * @param b
	 */
	public void setClipFilled(boolean b) {
		boolean old = isClipFilled();
		this.clipFilled = b;
		firePropertyChange("clipFilled", old, isClipFilled());
	}

	/**
	 * This variable indicates whether we have a non-updated display of the entries,
	 * where the changes were made when this window was invisible. this for instance
	 * happen when initiating the desktop after program-startup: the desktop is
	 * initiated, but the jEditorPane should not be filled with entries at that
	 * moment, because it might take too long for the startup. instead, we will do
	 * the update of the isplay later, when the window becomes visible.
	 */
	private boolean needsUpdate = false;

	/**
	 * This variable indicates whether we have a non-updated display of the entries,
	 * where the changes were made when this window was invisible. this for instance
	 * happen when initiating the desktop after program-startup: the desktop is
	 * initiated, but the jEditorPane should not be filled with entries at that
	 * moment, because it might take too long for the startup. instead, we will do
	 * the update of the isplay later, when the window becomes visible.
	 *
	 * @return
	 */
	public boolean isNeedsUpdate() {
		return needsUpdate;
	}

	/**
	 * This variable indicates whether we have a non-updated display of the entries,
	 * where the changes were made when this window was invisible. this for instance
	 * happen when initiating the desktop after program-startup: the desktop is
	 * initiated, but the jEditorPane should not be filled with entries at that
	 * moment, because it might take too long for the startup. instead, we will do
	 * the update of the isplay later, when the window becomes visible.
	 *
	 * @param b
	 */
	public void setNeedsUpdate(boolean b) {
		boolean old = isNeedsUpdate();
		this.needsUpdate = b;
		firePropertyChange("needsUpdate", old, isNeedsUpdate());
	}

	/**
	 * This variable indicates whether or not the fullscreen mode is supportet on
	 * the current system. if not, disable related icons...
	 */
	private boolean fullScreenSupp = false;

	/**
	 * This variable indicates whether or not the fullscreen mode is supportet on
	 * the current system. if not, disable related icons...
	 *
	 * @return
	 */
	public boolean isFullScreenSupp() {
		return fullScreenSupp;
	}

	/**
	 * This variable indicates whether or not the fullscreen mode is supportet on
	 * the current system. if not, disable related icons...
	 *
	 * @param b
	 */
	public void setFullScreenSupp(boolean b) {
		boolean old = isFullScreenSupp();
		this.fullScreenSupp = b;
		firePropertyChange("fullScreenSupp", old, isFullScreenSupp());
	}

	/**
	 * This variable indicates whether the user has selected a node at the very
	 * first position. depending on this, the action to move an entry/bullet up is
	 * en-/disabled.
	 */
	private boolean moveUpEnabled = false;

	/**
	 * This variable indicates whether the user has selected a node at the very
	 * first position. depending on this, the action to move an entry/bullet up is
	 * en-/disabled.
	 *
	 * @return
	 */
	public boolean isMoveUpEnabled() {
		return moveUpEnabled;
	}

	/**
	 * This variable indicates whether the user has selected a node at the very
	 * first position. depending on this, the action to move an entry/bullet up is
	 * en-/disabled.
	 *
	 * @param b
	 */
	public void setMoveUpEnabled(boolean b) {
		boolean old = isMoveUpEnabled();
		this.moveUpEnabled = b;
		firePropertyChange("moveUpEnabled", old, isMoveUpEnabled());
	}

	/**
	 * This variable indicates whether the user has selected a node at the very last
	 * position. depending on this, the action to move an entry/bullet down is
	 * en-/disabled.
	 */
	private boolean moveDownEnabled = false;

	/**
	 * This variable indicates whether the user has selected a node at the very last
	 * position. depending on this, the action to move an entry/bullet down is
	 * en-/disabled.
	 *
	 * @return
	 */
	public boolean isMoveDownEnabled() {
		return moveDownEnabled;
	}

	/**
	 * This variable indicates whether the user has selected a node at the very last
	 * position. depending on this, the action to move an entry/bullet down is
	 * en-/disabled.
	 *
	 * @param b
	 */
	public void setMoveDownEnabled(boolean b) {
		boolean old = isMoveDownEnabled();
		this.moveDownEnabled = b;
		firePropertyChange("moveDownEnabled", old, isMoveDownEnabled());
	}

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem addBulletMenuItem;
    private javax.swing.JMenuItem addEntryMenuItem;
    private javax.swing.JMenuItem addLuhmannCompleteMenuItem;
    private javax.swing.JMenuItem addLuhmannMenuItem;
    private javax.swing.JMenuItem applyAllModificationsMenuItem;
    private javax.swing.JMenuItem applyModificationsToOriginalMenuItem;
    private javax.swing.JMenuItem archiveDesktopMenuItem;
    private javax.swing.ButtonGroup buttonGroupDesktopView;
    private javax.swing.JMenuItem closeMenuItem;
    private javax.swing.JMenuItem commentMenuItem;
    private javax.swing.JMenuItem copyMenuItem;
    private javax.swing.JMenuItem cutMenuItem;
    private javax.swing.JMenuItem deleteMenuItem;
    private javax.swing.JMenu desktopMenuEdit;
    private javax.swing.JMenu desktopMenuFile;
    private javax.swing.JMenu desktopMenuFind;
    private javax.swing.JMenu desktopMenuView;
    private javax.swing.JMenuItem displayItemsMenuItem;
    private javax.swing.JMenuItem editEntryMenuItem;
    private javax.swing.JCheckBoxMenuItem entryNumberVisibleMenuItem;
    private javax.swing.JMenuItem exportDeskToSearch;
    private javax.swing.JMenuItem exportMenuItem;
    private javax.swing.JMenuItem exportMissingToSearch;
    private javax.swing.JMenuItem exportMultipleMenuItem;
    private javax.swing.JMenu exportSubMenu;
    private javax.swing.JMenuItem findMenuLiveNext;
    private javax.swing.JMenuItem findMenuLivePrev;
    private javax.swing.JMenuItem findMenuLiveSearch;
    private javax.swing.JCheckBoxMenuItem headingsVisibleMenuItem;
    private javax.swing.JMenuItem importArchivedDesktopMenuItem;
    private javax.swing.JMenuItem insertNewEntryMenuItem;
    private javax.swing.JButton jButtonLiveCancel;
    private javax.swing.JButton jButtonLiveNext;
    private javax.swing.JButton jButtonLivePrev;
    private javax.swing.JButton jButtonShowMultipleOccurencesDlg;
    private javax.swing.JComboBox jComboBoxDesktop;
    private javax.swing.JEditorPane jEditorPaneMain;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabelWordCount;
    private javax.swing.JMenuBar jMenuBarDesktop;
    private javax.swing.JMenuItem jMenuItemNotesCopy;
    private javax.swing.JMenuItem jMenuItemNotesCut;
    private javax.swing.JMenuItem jMenuItemNotesPaste;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanelLiveSearch;
    private javax.swing.JPopupMenu jPopupMenuCutCopyPaste;
    private javax.swing.JPopupMenu jPopupMenuDesktop;
    private javax.swing.JRadioButtonMenuItem jRadioButtonDesktopOnlyComments;
    private javax.swing.JRadioButtonMenuItem jRadioButtonDesktopWithComment;
    private javax.swing.JRadioButtonMenuItem jRadioButtonDesktopWithoutComments;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator10;
    private javax.swing.JSeparator jSeparator11;
    private javax.swing.JSeparator jSeparator12;
    private javax.swing.JSeparator jSeparator13;
    private javax.swing.JSeparator jSeparator14;
    private javax.swing.JSeparator jSeparator15;
    private javax.swing.JPopupMenu.Separator jSeparator16;
    private javax.swing.JSeparator jSeparator17;
    private javax.swing.JSeparator jSeparator18;
    private javax.swing.JSeparator jSeparator19;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JSeparator jSeparator20;
    private javax.swing.JSeparator jSeparator21;
    private javax.swing.JSeparator jSeparator22;
    private javax.swing.JPopupMenu.Separator jSeparator23;
    private javax.swing.JSeparator jSeparator24;
    private javax.swing.JSeparator jSeparator25;
    private javax.swing.JPopupMenu.Separator jSeparator26;
    private javax.swing.JSeparator jSeparator27;
    private javax.swing.JSeparator jSeparator28;
    private javax.swing.JToolBar.Separator jSeparator29;
    private javax.swing.JToolBar.Separator jSeparator3;
    private javax.swing.JPopupMenu.Separator jSeparator30;
    private javax.swing.JPopupMenu.Separator jSeparator31;
    private javax.swing.JToolBar.Separator jSeparator4;
    private javax.swing.JSeparator jSeparator5;
    private javax.swing.JSeparator jSeparator6;
    private javax.swing.JToolBar.Separator jSeparator7;
    private javax.swing.JPopupMenu.Separator jSeparator8;
    private javax.swing.JSeparator jSeparator9;
    private javax.swing.JSplitPane jSplitPaneDesktop1;
    private javax.swing.JSplitPane jSplitPaneDesktop2;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JTextArea jTextArea2;
    private javax.swing.JTextArea jTextArea3;
    private javax.swing.JTextField jTextFieldLiveSearch;
    private javax.swing.JToolBar jToolBarDesktop;
    private javax.swing.JTree jTreeDesktop;
    private javax.swing.JCheckBoxMenuItem luhmannIconVisible;
    private javax.swing.JMenuItem modifyEntryItem;
    private javax.swing.JMenuItem moveDownMenuItem;
    private javax.swing.JMenuItem moveUpMenuItem;
    private javax.swing.JMenuItem newDesktopMenuItem;
    private javax.swing.JMenuItem pasteMenuItem;
    private javax.swing.JMenuItem popupApplyModificationsEntry;
    private javax.swing.JMenuItem popupComment;
    private javax.swing.JMenuItem popupCopy;
    private javax.swing.JMenuItem popupCut;
    private javax.swing.JMenuItem popupDelete;
    private javax.swing.JMenuItem popupExportBullet;
    private javax.swing.JMenuItem popupExportBulletToSearch;
    private javax.swing.JMenuItem popupModifyEntry;
    private javax.swing.JMenuItem popupNewBullet;
    private javax.swing.JMenuItem popupNewEntry;
    private javax.swing.JMenuItem popupNewLuhmann;
    private javax.swing.JMenuItem popupPaste;
    private javax.swing.JMenuItem popupRefreshView;
    private javax.swing.JMenuItem popupRename;
    private javax.swing.JMenuItem popupShowEntryInMain;
    private javax.swing.JMenuItem printMenuItem;
    private javax.swing.JMenuItem renameBulletMenuItem;
    private javax.swing.JCheckBoxMenuItem showDesktopTreeEntryNumberMenuItem;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JButton tb_addluhmann;
    private javax.swing.JButton tb_comment;
    private javax.swing.JButton tb_copy;
    private javax.swing.JButton tb_cut;
    private javax.swing.JButton tb_delete;
    private javax.swing.JButton tb_modifyentry;
    private javax.swing.JButton tb_movedown;
    private javax.swing.JButton tb_moveup;
    private javax.swing.JButton tb_newbullet;
    private javax.swing.JButton tb_newentry;
    private javax.swing.JButton tb_paste;
    private javax.swing.JButton tb_refresh;
    private javax.swing.JButton tb_rename;
    private javax.swing.JMenuItem toggleNotesVisibility;
    private javax.swing.JMenuItem updateViewMenuItem;
    private javax.swing.JMenuItem viewFullScreenMenuItem;
    // End of variables declaration//GEN-END:variables

	private TaskProgressDialog taskDlg;
	private CModifyDesktopEntry modifyEntryDlg;
	private CDesktopExport exportWindow;
	private CBiggerEditField biggerEditDlg;
	private CDesktopDisplayItems desktopDisplayItemsDlg;
	private CDesktopMultipleExport desktopMultipleExportDlg;
	private CShowMultipleDesktopOccurences multipleOccurencesDlg;
}
